home *** CD-ROM | disk | FTP | other *** search
/ Micromanía 92 / CDMM92_1.ISO / SOF 2 SDK / sof2sdk-101.msi / _92D6AC311BB48EBA344BBABC89DA6AB0 / _353C2DBF0B0641318F337C10C1BA130D < prev    next >
Encoding:
Text File  |  2002-06-23  |  148.2 KB  |  5,456 lines

  1. // Copyright (C) 2001-2002 Raven Software, Inc.
  2. //
  3. // Main user interface 
  4. //
  5.  
  6. #include "ui_local.h"
  7. #include "../game/bg_public.h"
  8.  
  9. uiInfo_t uiInfo;
  10.  
  11. static const char *MonthAbbrev[] = 
  12. {
  13.     "Jan","Feb","Mar",
  14.     "Apr","May","Jun",
  15.     "Jul","Aug","Sep",
  16.     "Oct","Nov","Dec"
  17. };
  18.  
  19.  
  20. static const char *skillLevels[] = 
  21. {
  22.     "Amature",
  23.     "Gun For Hire",
  24.     "Consultant",
  25.     "Soldier of Fortune",
  26. };
  27.  
  28. static const char *netSources[] = 
  29. {
  30.     "Local",
  31.     "Internet",
  32.     "Favorites"
  33. };
  34.  
  35. static const serverFilter_t serverFilters[] = 
  36. {
  37.     {"All", "" },
  38.     {"Soldier of Fortune 2", "" },
  39. };
  40.  
  41. static char* netnames[] = 
  42. {
  43.     "???",
  44.     "UDP",
  45.     "IPX",
  46.     NULL
  47. };
  48.  
  49. static const int numNetSources                = sizeof(netSources) / sizeof(const char*);
  50. static const int numSkillLevels                = sizeof(skillLevels) / sizeof(const char*);
  51. static const int numServerFilters            = sizeof(serverFilters) / sizeof(serverFilter_t);
  52.  
  53. static int gamecodetoui[] = {4,2,3,0,5,1,6};
  54. static int uitogamecode[] = {4,6,2,3,1,5,7};
  55.  
  56. static playerInfo_t        playerInfo = { 0 };
  57.  
  58.  
  59. static void            UI_StartServerRefresh(qboolean full);
  60. static void            UI_StopServerRefresh( void );
  61. static void            UI_DoServerRefresh( void );
  62. static void            UI_FeederSelection(float feederID, int index);
  63. static void            UI_BuildServerDisplayList(qboolean force);
  64. static void            UI_BuildServerStatus(qboolean force);
  65. static void            UI_BuildFindPlayerList(qboolean force);
  66. static int QDECL    UI_ServersQsortCompare( const void *arg1, const void *arg2 );
  67. static int            UI_MapCountByGameType(void);
  68. static void            UI_ParseTeamInfo(const char *teamFile);
  69. static const char*    UI_SelectedMap(int index, int *actual);
  70. static const char*    UI_SelectedHead(int index, int *actual);
  71. static int            UI_GetIndexFromSelection(int actual);
  72. static void            UI_DrawVersionDownloadProgress(rectDef_t *rect, qhandle_t font, float scale, vec4_t color );
  73. static int            UI_MapCountForVote ( void );
  74.  
  75. /*
  76. ================
  77. vmMain
  78.  
  79. This is the only way control passes into the module.
  80. This must be the very first function compiled into the .qvm file
  81. ================
  82. */
  83. vmCvar_t  ui_new;
  84. vmCvar_t  ui_debug;
  85. vmCvar_t  ui_initialized;
  86. vmCvar_t  ui_sof2FirstRun;
  87.  
  88. void        _UI_Init         ( qboolean );
  89. void        _UI_Shutdown     ( void );
  90. qboolean    _UI_KeyEvent     ( int key, qboolean down );
  91. qboolean    _UI_MouseEvent     ( int dx, int dy );
  92. void        _UI_Refresh         ( int realtime );
  93.  
  94. int vmMain( int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10, int arg11  ) 
  95. {
  96.     switch ( command ) 
  97.     {
  98.         case UI_GETAPIVERSION:
  99.             return UI_API_VERSION;
  100.  
  101.         case UI_INIT:
  102.             _UI_Init(arg0);
  103.             return 0;
  104.  
  105.         case UI_SHUTDOWN:
  106.             _UI_Shutdown();
  107.             return 0;
  108.  
  109.         case UI_KEY_EVENT:
  110.             return _UI_KeyEvent( arg0, arg1 );
  111.  
  112.         case UI_MOUSE_EVENT:
  113.             return _UI_MouseEvent( arg0, arg1 );
  114.  
  115.         case UI_REFRESH:
  116.             _UI_Refresh( arg0 );
  117.             return 0;
  118.  
  119.         case UI_IS_FULLSCREEN:
  120.             return Menus_AnyFullScreenVisible();
  121.  
  122.         case UI_SET_ACTIVE_MENU:
  123.             UI_SetActiveMenu( arg0 );
  124.             return 0;
  125.  
  126.         case UI_CLOSEALL:
  127.             Menus_CloseAll ( );
  128.             return 0;
  129.  
  130.         case UI_CONSOLE_COMMAND:
  131.             return UI_ConsoleCommand(arg0);
  132.  
  133.         case UI_DRAW_CONNECT_SCREEN:
  134.             UI_DrawConnectScreen( arg0 );
  135.             return 0;
  136.  
  137.         case UI_DRAW_LOADING_SCREEN:
  138.             UI_DrawLoadingScreen();
  139.             return 0;
  140.  
  141.         case UI_HASUNIQUECDKEY: 
  142.             return qfalse; 
  143.     }
  144.  
  145.     return -1;
  146. }
  147.  
  148. /*
  149. ================
  150. AssetCache
  151.  
  152. PreCaches the assets for the main user interface
  153. =================
  154. */
  155. void AssetCache ( void ) 
  156. {
  157.     int n;
  158.  
  159.     // Scrollbar and slider assets
  160.     uiInfo.uiDC.Assets.scrollBar            = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR );
  161.     uiInfo.uiDC.Assets.scrollBarHoriz        = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_HORIZ );
  162.     uiInfo.uiDC.Assets.scrollBarArrowDown    = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWDOWN );
  163.     uiInfo.uiDC.Assets.scrollBarArrowUp        = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWUP );
  164.     uiInfo.uiDC.Assets.scrollBarArrowLeft    = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWLEFT );
  165.     uiInfo.uiDC.Assets.scrollBarArrowRight    = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWRIGHT );
  166.     uiInfo.uiDC.Assets.scrollBarThumb        = trap_R_RegisterShaderNoMip( ASSET_SCROLL_THUMB );
  167.     uiInfo.uiDC.Assets.sliderBar            = trap_R_RegisterShaderNoMip( ASSET_SLIDER_BAR );
  168.     uiInfo.uiDC.Assets.sliderThumb            = trap_R_RegisterShaderNoMip( ASSET_SLIDER_THUMB );
  169.  
  170.     // Load the shaders for all of the supported crosshairs
  171.     for( n = 0; n < NUM_CROSSHAIRS; n++ ) 
  172.     {
  173.         uiInfo.uiDC.Assets.crosshairShader[n] = trap_R_RegisterShaderNoMip( va("gfx/menus/crosshairs/ch%i", n) );
  174.     }
  175. }
  176.  
  177. /*
  178. ================
  179. _UI_DrawRectLeftRight
  180.  
  181. Draws the left and right sides of the rectangle
  182. =================
  183. */
  184. void _UI_DrawRectLeftRight ( float x, float y, float w, float h, float size ) 
  185. {
  186.     UI_AdjustFrom640( &x, &y, &w, &h );
  187.     size *= uiInfo.uiDC.xscale;
  188.     trap_R_DrawStretchPic( x, y, size, h, 0, 0, 0, 0, NULL, uiInfo.uiDC.whiteShader );
  189.     trap_R_DrawStretchPic( x + w - size, y, size, h, 0, 0, 0, 0, NULL, uiInfo.uiDC.whiteShader );
  190. }
  191.  
  192. /*
  193. ================
  194. _UI_DrawRectTopBottom
  195.  
  196. Draws the top and bottom sides of the rectangle
  197. =================
  198. */
  199. void _UI_DrawRectTopBottom ( float x, float y, float w, float h, float size ) 
  200. {
  201.     UI_AdjustFrom640( &x, &y, &w, &h );
  202.     size *= uiInfo.uiDC.yscale;
  203.     trap_R_DrawStretchPic( x, y, w, size, 0, 0, 0, 0, NULL, uiInfo.uiDC.whiteShader );
  204.     trap_R_DrawStretchPic( x, y + h - size, w, size, 0, 0, 0, 0, NULL, uiInfo.uiDC.whiteShader );
  205. }
  206.  
  207. /*
  208. ================
  209. UI_DrawRect
  210.  
  211. Coordinates are 640*480 virtual values
  212. =================
  213. */
  214. void _UI_DrawRect( float x, float y, float width, float height, float size, const float *color ) 
  215. {
  216.     trap_R_SetColor( color );
  217.  
  218.     _UI_DrawRectTopBottom(x, y, width, height, size);
  219.     _UI_DrawRectLeftRight(x, y, width, height, size);
  220.  
  221.     trap_R_SetColor( NULL );
  222. }
  223.  
  224. /*
  225. =================
  226. UI_DrawCenteredPic
  227. =================
  228. */
  229. void UI_DrawCenteredPic(qhandle_t image, int w, int h) 
  230. {
  231.     int x;
  232.     int    y;
  233.   
  234.     x = (SCREEN_WIDTH - w) / 2;
  235.     y = (SCREEN_HEIGHT - h) / 2;
  236.  
  237.     UI_DrawHandlePic (x, y, w, h, image);
  238. }
  239.  
  240.  
  241. /*
  242. =================
  243. _UI_Refresh
  244. =================
  245. */
  246. #define    UI_FPS_FRAMES    4
  247. void _UI_Refresh( int realtime )
  248. {
  249.     static int index;
  250.     static int    previousTimes[UI_FPS_FRAMES];
  251.     int            catcher;
  252.  
  253.     //if ( !( trap_Key_GetCatcher() & KEYCATCH_UI ) ) {
  254.     //    return;
  255.     //}
  256.  
  257.     uiInfo.uiDC.frameTime = realtime - uiInfo.uiDC.realTime;
  258.     uiInfo.uiDC.realTime = realtime;
  259.  
  260.     previousTimes[index % UI_FPS_FRAMES] = uiInfo.uiDC.frameTime;
  261.     index++;
  262.     if ( index > UI_FPS_FRAMES ) 
  263.     {
  264.         int i, total;
  265.         // average multiple frames together to smooth changes out a bit
  266.         total = 0;
  267.         for ( i = 0 ; i < UI_FPS_FRAMES ; i++ ) 
  268.         {
  269.             total += previousTimes[i];
  270.         }
  271.         if ( !total ) 
  272.         {
  273.             total = 1;
  274.         }
  275.         uiInfo.uiDC.FPS = 1000 * UI_FPS_FRAMES / total;
  276.     }
  277.  
  278.     // Update all of the user interface cvars
  279.     UI_UpdateCvars();
  280.  
  281.     // Render the menus if there are any
  282.     if (Menu_Count() > 0) 
  283.     {
  284.         // paint all the menus
  285.         Menu_PaintAll();
  286.  
  287.         // refresh server browser list
  288.         UI_DoServerRefresh();
  289.  
  290.         // refresh server status
  291.         UI_BuildServerStatus(qfalse);
  292.  
  293.         // refresh find player list
  294.         UI_BuildFindPlayerList(qfalse);
  295.     } 
  296.     
  297.     // draw cursor
  298.     UI_SetColor( NULL );
  299.  
  300.     catcher = trap_Key_GetCatcher ( );
  301.     if (Menu_Count() > 0 && (catcher&KEYCATCH_UI) && !(catcher & KEYCATCH_NUMBERSONLY) ) 
  302.     {
  303.         UI_DrawHandlePic( uiInfo.uiDC.cursorx - 16, uiInfo.uiDC.cursory - 16, 32, 32, uiInfo.uiDC.Assets.cursor);
  304.     }
  305. }
  306.  
  307. /*
  308. =================
  309. _UI_Shutdown
  310. =================
  311. */
  312. void _UI_Shutdown( void ) 
  313. {
  314.     if (playerInfo.playerG2Model)
  315.     {
  316.         trap_G2API_CleanGhoul2Models(&playerInfo.playerG2Model);
  317.     }
  318.  
  319.     trap_LAN_SaveCachedServers();
  320. }
  321.  
  322. char *defaultMenu = NULL;
  323.  
  324. char *GetMenuBuffer(const char *filename) {
  325.     int    len;
  326.     fileHandle_t    f;
  327.     static char buf[MAX_MENUFILE];
  328.  
  329.     len = trap_FS_FOpenFile( filename, &f, FS_READ );
  330.     if ( !f ) {
  331.         trap_Print( va( S_COLOR_RED "menu file not found: %s, using default\n", filename ) );
  332.         return defaultMenu;
  333.     }
  334.     if ( len >= MAX_MENUFILE ) {
  335.         trap_Print( va( S_COLOR_RED "menu file too large: %s is %i, max allowed is %i", filename, len, MAX_MENUFILE ) );
  336.         trap_FS_FCloseFile( f );
  337.         return defaultMenu;
  338.     }
  339.  
  340.     trap_FS_Read( buf, len, f );
  341.     buf[len] = 0;
  342.     trap_FS_FCloseFile( f );
  343.     //COM_Compress(buf);
  344.   return buf;
  345.  
  346. }
  347.  
  348. qboolean Asset_Parse(int handle) {
  349.     pc_token_t token;
  350.     const char *tempStr;
  351.  
  352.     if (!trap_PC_ReadToken(handle, &token))
  353.         return qfalse;
  354.     if (Q_stricmp(token.string, "{") != 0) {
  355.         return qfalse;
  356.     }
  357.     
  358.     while ( 1 ) {
  359.  
  360.         memset(&token, 0, sizeof(pc_token_t));
  361.  
  362.         if (!trap_PC_ReadToken(handle, &token))
  363.             return qfalse;
  364.  
  365.         if (Q_stricmp(token.string, "}") == 0) {
  366.             return qtrue;
  367.         }
  368.  
  369.         // font
  370.         if (Q_stricmp(token.string, "defaultFont") == 0) 
  371.         {
  372.             if (!PC_String_Parse(handle, &tempStr)) 
  373.             {
  374.                 return qfalse;
  375.             }
  376.             uiInfo.uiDC.Assets.defaultFont = trap_R_RegisterFont(tempStr );
  377.             uiInfo.uiDC.Assets.fontRegistered = qtrue;
  378.             continue;
  379.         }
  380.  
  381.         if (Q_stricmp(token.string, "cursor") == 0) 
  382.         {
  383.             if (!PC_String_Parse(handle, &uiInfo.uiDC.Assets.cursorStr))
  384.             {
  385.                 Com_Printf(S_COLOR_YELLOW,"Bad 1st parameter for keyword 'cursor'");
  386.                 return qfalse;
  387.             }
  388.             uiInfo.uiDC.Assets.cursor = trap_R_RegisterShaderNoMip( uiInfo.uiDC.Assets.cursorStr);
  389.             continue;
  390.         }
  391.  
  392.         // itemFocusSound
  393.         if (Q_stricmp(token.string, "itemFocusSound") == 0) {
  394.             if (!PC_String_Parse(handle, &tempStr)) {
  395.                 return qfalse;
  396.             }
  397.             uiInfo.uiDC.Assets.itemFocusSound = trap_S_RegisterSound( tempStr );
  398.             continue;
  399.         }
  400.  
  401.         if (Q_stricmp(token.string, "fadeClamp") == 0) {
  402.             if (!PC_Float_Parse(handle, &uiInfo.uiDC.Assets.fadeClamp)) {
  403.                 return qfalse;
  404.             }
  405.             continue;
  406.         }
  407.  
  408.         if (Q_stricmp(token.string, "fadeCycle") == 0) {
  409.             if (!PC_Int_Parse(handle, &uiInfo.uiDC.Assets.fadeCycle)) {
  410.                 return qfalse;
  411.             }
  412.             continue;
  413.         }
  414.  
  415.         if (Q_stricmp(token.string, "fadeAmount") == 0) {
  416.             if (!PC_Float_Parse(handle, &uiInfo.uiDC.Assets.fadeAmount)) {
  417.                 return qfalse;
  418.             }
  419.             continue;
  420.         }
  421.  
  422.         if (Q_stricmp(token.string, "shadowX") == 0) {
  423.             if (!PC_Float_Parse(handle, &uiInfo.uiDC.Assets.shadowX)) {
  424.                 return qfalse;
  425.             }
  426.             continue;
  427.         }
  428.  
  429.         if (Q_stricmp(token.string, "shadowY") == 0) {
  430.             if (!PC_Float_Parse(handle, &uiInfo.uiDC.Assets.shadowY)) {
  431.                 return qfalse;
  432.             }
  433.             continue;
  434.         }
  435.  
  436.         if (Q_stricmp(token.string, "shadowColor") == 0) {
  437.             if (!PC_Color_Parse(handle, &uiInfo.uiDC.Assets.shadowColor)) {
  438.                 return qfalse;
  439.             }
  440.             uiInfo.uiDC.Assets.shadowFadeClamp = uiInfo.uiDC.Assets.shadowColor[3];
  441.             continue;
  442.         }
  443.  
  444.         if (Q_stricmp(token.string, "shader") == 0) 
  445.         {
  446.             if (!PC_String_Parse(handle, &tempStr)) 
  447.             {
  448.                 return qfalse;
  449.             }
  450.             trap_R_RegisterShaderNoMip ( tempStr );
  451.             continue;
  452.         }
  453.     }
  454.     return qfalse;
  455. }
  456.  
  457. void UI_Report() 
  458. {
  459.     String_Report();
  460. }
  461.  
  462. void UI_ParseMenu(const char *menuFile) 
  463. {
  464.     int            handle;
  465.     pc_token_t    token;
  466.  
  467.     handle = trap_PC_LoadSource(menuFile);
  468.     if (!handle) 
  469.     {
  470.         return;
  471.     }
  472.  
  473.     while ( 1 ) 
  474.     {
  475.         memset(&token, 0, sizeof(pc_token_t));
  476.         if (!trap_PC_ReadToken( handle, &token )) 
  477.         {
  478.             break;
  479.         }
  480.  
  481.         if ( token.string[0] == '}' ) 
  482.         {
  483.             break;
  484.         }
  485.  
  486.         if (Q_stricmp(token.string, "assetGlobalDef") == 0) 
  487.         {
  488.             if (Asset_Parse(handle)) 
  489.             {
  490.                 continue;
  491.             } 
  492.             else 
  493.             {
  494.                 break;
  495.             }
  496.         }
  497.  
  498.         if (Q_stricmp(token.string, "menudef") == 0) 
  499.         {
  500.             // start a new menu
  501.             Menu_New(handle);
  502.         }
  503.     }
  504.  
  505.     trap_PC_FreeSource(handle);
  506. }
  507.  
  508. qboolean Load_Menu(int handle) 
  509. {
  510.     pc_token_t token;
  511.  
  512.     if (!trap_PC_ReadToken(handle, &token))
  513.     {
  514.         return qfalse;
  515.     }
  516.  
  517.     if (token.string[0] != '{') 
  518.     {
  519.         return qfalse;
  520.     }
  521.  
  522.     while ( 1 ) 
  523.     {
  524.         if (!trap_PC_ReadToken(handle, &token))
  525.         {
  526.             return qfalse;
  527.         }
  528.     
  529.         if ( token.string[0] == 0 ) 
  530.         {
  531.             return qfalse;
  532.         }
  533.  
  534.         if ( token.string[0] == '}' ) 
  535.         {
  536.             return qtrue;
  537.         }
  538.  
  539.         UI_ParseMenu(token.string); 
  540.     }
  541.  
  542.     return qfalse;
  543. }
  544.  
  545. extern menuDef_t Menus[MAX_MENUS];      // defined menus
  546. extern int menuCount;               // how many
  547.  
  548. /*
  549. =================
  550. UI_LoadMenus
  551.  
  552. Loads all menus from the given text file and optionally resets the 
  553. existing menus
  554. =================
  555. */
  556. void UI_LoadMenus ( const char *menuFile, qboolean reset ) 
  557. {
  558.     pc_token_t    token;
  559.     int            handle;
  560.     int            start;
  561.  
  562.     start = trap_Milliseconds();
  563.  
  564.     trap_PC_LoadGlobalDefines ( "ui/menudef.h" );
  565.  
  566.     handle = trap_PC_LoadSource( menuFile );
  567.     if (!handle) 
  568.     {
  569.         trap_Error( va( S_COLOR_RED "menu file not found: %s, unable to continue!\n", menuFile ) );
  570.     }
  571.  
  572.     ui_new.integer = 1;
  573.  
  574.     if (reset) 
  575.     {
  576.         Menu_Reset();
  577.     }
  578.  
  579.     while ( 1 ) 
  580.     {
  581.         if (!trap_PC_ReadToken(handle, &token))
  582.         {
  583.             break;
  584.         }
  585.  
  586.         if( token.string[0] == 0 || token.string[0] == '}') 
  587.         {
  588.             break;
  589.         }
  590.  
  591.         if ( token.string[0] == '}' ) 
  592.         {
  593.             break;
  594.         }
  595.  
  596.         if (Q_stricmp(token.string, "loadmenu") == 0) 
  597.         {
  598.             if (Load_Menu(handle)) 
  599.             {
  600.                 if (menuCount == 1 && Menus_FindByName("Loading"))
  601.                 {
  602.                     // handle double / tripple buffering...
  603.                     UI_UpdateScreen(qtrue);
  604.                     UI_UpdateScreen(qtrue);
  605.                     UI_UpdateScreen(qtrue);
  606.                 }
  607.                 continue;
  608.             } 
  609.             else 
  610.             {
  611.                 break;
  612.             }
  613.         }
  614.     }
  615.  
  616.     Com_Printf("UI total menu load time = %d ms\n", trap_Milliseconds() - start);
  617.  
  618.     trap_PC_FreeSource( handle );
  619.  
  620.     trap_PC_RemoveAllGlobalDefines ( );
  621. }
  622.  
  623. /*
  624. =================
  625. UI_Reload
  626.  
  627. Reloads the 
  628. =================
  629. */
  630. void UI_Reload ( void ) 
  631. {
  632.     char        lastName[1024];
  633.     menuDef_t    *menu;
  634.     int            actual;
  635.  
  636.     // Retail the last active menu so it 
  637.     // can be opened again
  638.     menu = Menu_GetFocused();
  639.     if (menu && menu->window.name) 
  640.     {
  641.         strcpy(lastName, menu->window.name);
  642.     }
  643.  
  644.     // Reinitialize the strings
  645.     String_Init();
  646.  
  647.     // Read in the gametype list for the various user interface screens
  648.     BG_BuildGametypeList ( );
  649.  
  650.     // Load the list of arenas available for play
  651.     UI_LoadArenas();
  652.  
  653.     UI_SelectedMap ( 0, &actual );
  654.     trap_Cvar_Set("ui_mapIndex", "0");
  655.     ui_currentNetMap.integer = actual;
  656.     trap_Cvar_Set("ui_currentNetMap", va("%d",actual));
  657.     trap_Cvar_Set("ui_currentNetMapName", uiInfo.mapList[actual].mapLoadName );
  658.  
  659.     // Load all of the menus files now
  660.     UI_LoadMenus( uiInfo.menusFile, qtrue);
  661.  
  662.     // Close any open menus and open the last menu that was open before reloading
  663.     Menus_CloseAll();
  664.     Menus_ActivateByName(lastName);
  665. }
  666.  
  667. void UI_DrawObjectivePhotos ( rectDef_t *rect, qhandle_t font, float scale, vec4_t color )
  668. {
  669.     int   gametype = (int) trap_Cvar_VariableValue ( "ui_about_gametype" );
  670.     int   count;
  671.     int   index;
  672.     float width;
  673.     float x;
  674.     float spacing;
  675.     float height;
  676.     float fontheight;
  677.  
  678.     // Figure out how many photos there are
  679.     for ( count = 0; bg_gametypeData[gametype].photos[count].name && count < MAX_GAMETYPE_PHOTOS; count ++ );
  680.  
  681.     // Images should be saved as 256 x 192
  682.     width  = (rect->w / count) - ((count-1) * 10);
  683.     height = width / 256 * 192;
  684.  
  685.     // If height is too big for the given rect, scale them down again
  686.     if ( height > rect->h )
  687.     {
  688.         width = rect->h / height * width;
  689.         height = rect->h;
  690.     }
  691.     
  692.     // How much space is there between each photo horizontally?
  693.     spacing = (rect->w - (width * count)) / (count-1);
  694.  
  695.     fontheight = trap_R_GetTextHeight ( "W", font, scale, 0 );
  696.  
  697.     for ( x = rect->x, index = 0; index < count; index ++ )
  698.     {
  699.         qhandle_t pic;
  700.  
  701.         pic = trap_R_RegisterShaderNoMip ( va("gfx/menus/levelshots/%s_%s_%s",
  702.                                       UI_Cvar_VariableString ( "ui_about_mapname" ),
  703.                                       bg_gametypeData[gametype].name,
  704.                                       bg_gametypeData[gametype].photos[index].name ) );
  705.  
  706.         if ( pic )
  707.         {
  708.             UI_DrawText ( x, rect->y - fontheight - 2, font, scale, color, bg_gametypeData[gametype].photos[index].displayName, 0, 0 );
  709.             UI_DrawHandlePic ( x, rect->y, width, height, pic );
  710.         }
  711.  
  712.         x += spacing;
  713.         x += width;
  714.     }    
  715. }
  716.  
  717. // ui_gameType assumes gametype 0 is -1 ALL and will not show
  718. static void UI_DrawGameType(rectDef_t *rect, qhandle_t font, float scale, vec4_t color ) 
  719. {
  720.     UI_DrawText (rect->x, rect->y, font, scale, color, bg_gametypeData[(int)trap_Cvar_VariableValue ( "ui_about_gametype" )].displayName, 0, 0 );
  721. }
  722.  
  723. static void UI_DrawNetGameType(rectDef_t *rect, qhandle_t font, float scale, vec4_t color ) 
  724. {
  725.     if ( ui_netGameType.integer < 0 || ui_netGameType.integer >= bg_gametypeCount ) 
  726.     {
  727.         trap_Cvar_Set("ui_netGameType", "0");
  728.         trap_Cvar_Set("ui_actualNetGameType", "0");
  729.  
  730.         trap_Cvar_Update ( &ui_netGameType );
  731.         trap_Cvar_Update ( &ui_actualNetGameType );
  732.     }
  733.  
  734.     UI_DrawText (rect->x, rect->y, font, scale, color, bg_gametypeData[ ui_netGameType.integer ].displayName, 0, 0 );
  735. }
  736.  
  737. static void UI_DrawJoinGameType(rectDef_t *rect, qhandle_t font, float scale, vec4_t color ) 
  738. {
  739.      if ( ui_joinGameType.integer < 0 || ui_joinGameType.integer > bg_gametypeCount ) 
  740.     {
  741.         trap_Cvar_Set("ui_joinGameType", "0");
  742.     }
  743.  
  744.     if ( ui_joinGameType.integer == 0 )
  745.     {
  746.         UI_DrawText(rect->x, rect->y, font, scale, color, "All", 0, 0 );
  747.     }
  748.     else
  749.     {
  750.         UI_DrawText(rect->x, rect->y, font, scale, color, bg_gametypeData[ui_joinGameType.integer-1].displayName, 0, 0 );
  751.     }
  752. }
  753.  
  754. static void UI_DrawPreviewCinematic(rectDef_t *rect, float scale, vec4_t color) {
  755.     if (uiInfo.previewMovie > -2) {
  756.         uiInfo.previewMovie = trap_CIN_PlayCinematic(va("%s.roq", uiInfo.movieList[uiInfo.movieIndex]), 0, 0, 0, 0, (CIN_loop | CIN_silent) );
  757.         if (uiInfo.previewMovie >= 0) {
  758.           trap_CIN_RunCinematic(uiInfo.previewMovie);
  759.             trap_CIN_SetExtents(uiInfo.previewMovie, rect->x, rect->y, rect->w, rect->h);
  760.              trap_CIN_DrawCinematic(uiInfo.previewMovie);
  761.         } else {
  762.             uiInfo.previewMovie = -2;
  763.         }
  764.     } 
  765.  
  766. }
  767.  
  768. static void UI_DrawSkill(rectDef_t *rect, qhandle_t font, float scale, vec4_t color ) 
  769. {
  770.     int i;
  771.     
  772.     i = trap_Cvar_VariableValue( "g_botSkill" );
  773.     
  774.     if (i < 1 || i > numSkillLevels) 
  775.     {
  776.         i = 1;
  777.     }
  778.  
  779.     UI_DrawText (rect->x, rect->y, font, scale, color, skillLevels[i-1],0, 0 );
  780. }
  781.  
  782.  
  783. static void UI_DrawTeamName(rectDef_t *rect, qhandle_t font, float scale, vec4_t color, qboolean blue ) 
  784. {
  785.     char name[MAX_QPATH];
  786.     trap_Cvar_VariableStringBuffer ( va("ui_%steamname", blue?"blue":"red"), name, MAX_QPATH );
  787.  
  788.     UI_DrawText (rect->x, rect->y, font, scale, color, name,0, 0 );
  789. }
  790.  
  791. static void UI_DrawTeamIdentity ( rectDef_t *rect, team_t team, int index )
  792. {
  793.     if ( uiInfo.identityTeams[team][index] && uiInfo.identityTeams[team][index]->mIcon )
  794.     {
  795.         UI_DrawHandlePic( rect->x + 2, rect->y + 2, rect->w - 4, rect->h - 4, uiInfo.identityTeams[team][index]->mIcon);
  796.     }
  797.     else
  798.     {
  799.         static vec4_t color = {0,0,0,0.25f};
  800.         UI_DrawRect ( rect->x + 2, rect->y + 2, rect->w - 4, rect->h -4, color );
  801.     }
  802. }
  803.  
  804. static void UI_DrawMapPreview(rectDef_t *rect, float scale, vec4_t color, qboolean net) 
  805. {
  806.     int map = (net) ? ui_currentNetMap.integer : ui_currentMap.integer;
  807.     if (map < 0 || map > uiInfo.mapCount) 
  808.     {
  809.         if (net) 
  810.         {
  811.             int actual;
  812.             trap_Cvar_Set("ui_mapIndex", "0");
  813.             UI_SelectedMap ( 0, &actual );
  814.             ui_currentNetMap.integer = actual;
  815.             trap_Cvar_Set("ui_currentNetMap", va("%d",actual));
  816.             trap_Cvar_Set("ui_currentNetMapName", uiInfo.mapList[actual].mapLoadName );
  817.         } 
  818.         else 
  819.         {
  820.             ui_currentMap.integer = 0;
  821.             trap_Cvar_Set("ui_currentMap", "0");
  822.         }
  823.         map = 0;
  824.     }
  825.  
  826.     if (uiInfo.mapList[map].levelShot == -1) 
  827.     {
  828.         uiInfo.mapList[map].levelShot = trap_R_RegisterShaderNoMip(uiInfo.mapList[map].imageName);
  829.     }
  830.  
  831.     if (uiInfo.mapList[map].levelShot > 0) {
  832.         UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.mapList[map].levelShot);
  833.     } else {
  834.         UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, trap_R_RegisterShaderNoMip("gfx/menus/levelshots/unknownmap_mp"));
  835.     }
  836. }                         
  837.  
  838. static void UI_DrawMapCinematic(rectDef_t *rect, float scale, vec4_t color, qboolean net) 
  839. {
  840.     int map = (net) ? ui_currentNetMap.integer : ui_currentMap.integer; 
  841.     if (map < 0 || map > uiInfo.mapCount) 
  842.     {
  843.         if (net) 
  844.         {
  845.             int actual;
  846.             trap_Cvar_Set("ui_mapIndex", "0");
  847.             UI_SelectedMap ( 0, &actual );
  848.             ui_currentNetMap.integer = actual;
  849.             trap_Cvar_Set("ui_currentNetMap", va("%d",actual));
  850.             trap_Cvar_Set("ui_currentNetMapName", uiInfo.mapList[actual].mapLoadName );
  851.         } 
  852.         else 
  853.         {
  854.             ui_currentMap.integer = 0;
  855.             trap_Cvar_Set("ui_currentMap", "0");
  856.         }
  857.         
  858.         map = 0;
  859.     }
  860.  
  861.     if (uiInfo.mapList[map].cinematic >= -1) 
  862.     {
  863.         if (uiInfo.mapList[map].cinematic == -1) 
  864.         {
  865.             uiInfo.mapList[map].cinematic = trap_CIN_PlayCinematic(va("%s.roq", uiInfo.mapList[map].mapLoadName), 0, 0, 0, 0, (CIN_loop | CIN_silent) );
  866.         }
  867.         if (uiInfo.mapList[map].cinematic >= 0) 
  868.         {
  869.             trap_CIN_RunCinematic(uiInfo.mapList[map].cinematic);
  870.             trap_CIN_SetExtents(uiInfo.mapList[map].cinematic, rect->x, rect->y, rect->w, rect->h);
  871.             trap_CIN_DrawCinematic(uiInfo.mapList[map].cinematic);
  872.         } 
  873.         else 
  874.         {
  875.             uiInfo.mapList[map].cinematic = -2;
  876.         }
  877.     } 
  878.     else 
  879.     {
  880.         UI_DrawMapPreview(rect, scale, color, net);
  881.     }
  882. }
  883.  
  884. static qboolean updateModel = qtrue;
  885.  
  886.  
  887. /*
  888. ================
  889. UI_DrawOutfittingBackground
  890.  
  891. Draws the slot background
  892. ================
  893. */
  894. static void UI_DrawOutfittingBackground ( rectDef_t* rect, vec4_t color, int slot )
  895. {
  896.     vec4_t  col;
  897.  
  898.     VectorCopy4 ( color, col );
  899.  
  900.     if ( bg_outfittings[uiInfo.outfittingItemGroup].items[slot] == -1 )
  901.     {
  902.         col[3] *= 0.5f;
  903.     }
  904.     else
  905.     {
  906.         int item = bg_outfittingGroups[slot][bg_outfittings[uiInfo.outfittingItemGroup].items[slot]];
  907.  
  908.         if ( item <= 0 )
  909.         {
  910.             col[3] *= 0.5f;
  911.         }
  912.     }
  913.  
  914.     trap_R_SetColor ( col );
  915.     UI_DrawHandlePic ( rect->x, rect->y, rect->w, rect->h, uiInfo.uiDC.whiteShader );
  916. }
  917.  
  918. /*
  919. ================
  920. UI_DrawOutfittingSlotName
  921.  
  922. Draw the name of the weapon
  923. ================
  924. */
  925. static void UI_DrawOutfittingSlotName ( rectDef_t *rect, qhandle_t font, float scale, vec4_t color, int slot )
  926. {
  927.     const char* s;
  928.     int            item;
  929.     float        w;
  930.  
  931.     // Handle the case where there is nothing at all available for this group
  932.     if ( bg_outfittings[uiInfo.outfittingItemGroup].items[slot] == -1 )
  933.     {
  934.         s = "NONE";
  935.     }
  936.     else
  937.     {
  938.         item = bg_outfittingGroups[slot][bg_outfittings[uiInfo.outfittingItemGroup].items[slot]];
  939.         if ( item <= 0 )
  940.         {
  941.             s = "NONE";
  942.         }
  943.         else
  944.         {
  945.             s = bg_itemlist[item].pickup_name;
  946.         }
  947.     }
  948.  
  949.     w = trap_R_GetTextWidth ( s, font, scale, 0 );    
  950.  
  951.     UI_DrawText ( rect->x - w, rect->y, font, scale, color, s, 0, 0 );    
  952. }
  953.  
  954. /*
  955. ================
  956. UI_DrawOutfittingSlotRender
  957.  
  958. Draw the weapon render for the given outfitting slot
  959. ================
  960. */
  961. static void UI_DrawOutfittingSlotRender ( rectDef_t *rect, int slot )
  962. {
  963.     qhandle_t    shader;
  964.     const char*    name;
  965.  
  966.     // Nothing at all? Then draw a black square
  967.     if ( bg_outfittings[uiInfo.outfittingItemGroup].items[slot] == -1 )
  968.     {
  969.         return;
  970.     }
  971.     
  972.     name = bg_itemlist[bg_outfittingGroups[slot][bg_outfittings[uiInfo.outfittingItemGroup].items[slot]]].render;
  973.     if ( !name )
  974.     {
  975.         return;
  976.     }
  977.  
  978.     // This is a bit hacky, but any render with a * in the front of it
  979.     // is only half size
  980.     if ( *name == '*')
  981.     {
  982.         rect->x += rect->w / 4;
  983.         rect->w /= 2;
  984.         name ++;
  985.     }
  986.  
  987.     shader = trap_R_RegisterShaderNoMip ( name );
  988.  
  989.     UI_DrawHandlePic ( rect->x, rect->y, rect->w, rect->h, shader );
  990. }
  991.  
  992. static void UI_DrawPlayerModel(rectDef_t *rect) 
  993. {
  994.     vec3_t    viewangles;
  995.     vec3_t    moveangles;
  996.     char    identity[MAX_QPATH];
  997.  
  998.     if ( (int)trap_Cvar_VariableValue ( "ui_info_teamgame" ) )
  999.     {
  1000.         strcpy(identity, UI_Cvar_VariableString("team_identity"));
  1001.     }
  1002.     else
  1003.     {
  1004.         strcpy(identity, UI_Cvar_VariableString("identity"));
  1005.     }
  1006.  
  1007.     if (updateModel) 
  1008.     {
  1009.         if (playerInfo.playerG2Model)
  1010.         {
  1011.             trap_G2API_CleanGhoul2Models(&playerInfo.playerG2Model);
  1012.         }
  1013.  
  1014.           memset( &playerInfo, 0, sizeof(playerInfo_t) );
  1015.           viewangles[YAW]   = 180 - 10;
  1016.           viewangles[PITCH] = 0;
  1017.           viewangles[ROLL]  = 0;
  1018.           VectorClear( moveangles );
  1019.         UI_PlayerInfo_SetIdentity ( &playerInfo, identity );
  1020.         UI_PlayerInfo_SetInfo( &playerInfo, LEGS_WALK, TORSO_IDLE_PISTOL, viewangles, vec3_origin, WP_FIRST_RANGED_WEAPON, qfalse );
  1021.         updateModel = qfalse;
  1022.     }
  1023.  
  1024.     UI_DrawPlayer( rect->x, rect->y, rect->w, rect->h, &playerInfo, uiInfo.uiDC.realTime / 2);
  1025. }
  1026.  
  1027. static void UI_DrawNetSource(rectDef_t *rect, qhandle_t font, float scale, vec4_t color ) 
  1028. {
  1029.     if (ui_netSource.integer < 0 || ui_netSource.integer > numNetSources) 
  1030.     {
  1031.         ui_netSource.integer = 0;
  1032.     }
  1033.  
  1034.     UI_DrawText (rect->x, rect->y, font, scale, color, va("Source: %s", netSources[ui_netSource.integer]), 0, 0 );
  1035. }
  1036.  
  1037. static void UI_DrawNetMapPreview(rectDef_t *rect, float scale, vec4_t color) {
  1038.  
  1039.     if (uiInfo.serverStatus.currentServerPreview > 0) {
  1040.         UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.serverStatus.currentServerPreview);
  1041.     } else {
  1042.         UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, trap_R_RegisterShaderNoMip("gfx/menus/levelshots/unknownmap_mp"));
  1043.     }
  1044. }
  1045.  
  1046. static void UI_DrawNetMapCinematic(rectDef_t *rect, float scale, vec4_t color) 
  1047. {
  1048.     if (ui_currentNetMap.integer < 0 || ui_currentNetMap.integer > uiInfo.mapCount) 
  1049.     {
  1050.         int actual;
  1051.         trap_Cvar_Set("ui_mapIndex", "0");
  1052.         UI_SelectedMap ( 0, &actual );
  1053.         ui_currentNetMap.integer = actual;
  1054.         trap_Cvar_Set("ui_currentNetMap", va("%d",actual));
  1055.         trap_Cvar_Set("ui_currentNetMapName", uiInfo.mapList[actual].mapLoadName );
  1056.     }
  1057.  
  1058.     if (uiInfo.serverStatus.currentServerCinematic >= 0) 
  1059.     {
  1060.       trap_CIN_RunCinematic(uiInfo.serverStatus.currentServerCinematic);
  1061.       trap_CIN_SetExtents(uiInfo.serverStatus.currentServerCinematic, rect->x, rect->y, rect->w, rect->h);
  1062.        trap_CIN_DrawCinematic(uiInfo.serverStatus.currentServerCinematic);
  1063.     } 
  1064.     else 
  1065.     {
  1066.         UI_DrawNetMapPreview(rect, scale, color);
  1067.     }
  1068. }
  1069.  
  1070. static void UI_DrawNetFilter(rectDef_t *rect, qhandle_t font, float scale, vec4_t color ) 
  1071. {
  1072.     if (ui_serverFilterType.integer < 0 || ui_serverFilterType.integer > numServerFilters) 
  1073.     {
  1074.         ui_serverFilterType.integer = 0;
  1075.     }
  1076.  
  1077.     UI_DrawText (rect->x, rect->y, font, scale, color, va("Filter: %s", serverFilters[ui_serverFilterType.integer].description), 0, 0 );
  1078. }
  1079.  
  1080.  
  1081. static const char *UI_EnglishMapName(const char *map) {
  1082.     int i;
  1083.     for (i = 0; i < uiInfo.mapCount; i++) {
  1084.         if (Q_stricmp(map, uiInfo.mapList[i].mapLoadName) == 0) {
  1085.             return uiInfo.mapList[i].mapName;
  1086.         }
  1087.     }
  1088.     return "";
  1089. }
  1090.  
  1091. static void UI_DrawAllMapsSelection(rectDef_t *rect, qhandle_t font, float scale, vec4_t color, int textStyle, qboolean net) 
  1092. {
  1093.     int map = (net) ? ui_currentNetMap.integer : ui_currentMap.integer;
  1094.     
  1095.     if (map >= 0 && map < uiInfo.mapCount) 
  1096.     {
  1097.         UI_DrawText (rect->x, rect->y, font, scale, color, uiInfo.mapList[map].mapName, 0, 0 );
  1098.     }
  1099. }
  1100.  
  1101. static int UI_OwnerDrawWidth(int ownerDraw, qhandle_t font, float scale ) 
  1102. {
  1103.     const char    *s = NULL;
  1104.  
  1105.     switch (ownerDraw) 
  1106.     {
  1107.         case UI_GAMETYPE:
  1108.             s = bg_gametypeData[ui_gameType.integer].displayName;
  1109.             break;
  1110.  
  1111.         case UI_SKILL:
  1112.             {
  1113.                 int    i;
  1114.  
  1115.                 i = trap_Cvar_VariableValue( "g_botSkill" );
  1116.                 if (i < 1 || i > numSkillLevels) 
  1117.                 {
  1118.                     i = 1;
  1119.                 }
  1120.                 s = skillLevels[i-1];
  1121.             }
  1122.             break;
  1123.    
  1124.         case UI_NETSOURCE:
  1125.             if (ui_netSource.integer < 0 || ui_netSource.integer >= bg_gametypeCount) 
  1126.             {
  1127.                 ui_netSource.integer = 0;
  1128.             }
  1129.             s = va("Source: %s", netSources[ui_netSource.integer]);
  1130.             break;
  1131.  
  1132.         case UI_NETFILTER:
  1133.             if (ui_serverFilterType.integer < 0 || ui_serverFilterType.integer > numServerFilters) {
  1134.                 ui_serverFilterType.integer = 0;
  1135.             }
  1136.             s = va("Filter: %s", serverFilters[ui_serverFilterType.integer].description );
  1137.             break;
  1138.  
  1139.         case UI_ALLMAPS_SELECTION:
  1140.             break;
  1141.  
  1142.         case UI_SERVERREFRESHDATE:
  1143.             s = UI_Cvar_VariableString(va("ui_lastServerRefresh_%i", ui_netSource.integer));
  1144.             break;
  1145.     
  1146.         default:
  1147.             break;
  1148.     }
  1149.  
  1150.     if (s) 
  1151.     {
  1152.         return trap_R_GetTextWidth (s, font, scale, 0 );
  1153.     }
  1154.  
  1155.     return 0;
  1156. }
  1157.  
  1158. static void UI_DrawBotName(rectDef_t *rect, qhandle_t font, float scale, vec4_t color ) 
  1159. {
  1160.     int            value = uiInfo.botIndex;
  1161.     const char    *text = "";
  1162.  
  1163.     if (value >= UI_GetNumBots()) 
  1164.     {
  1165.         value = 0;
  1166.     }
  1167.  
  1168.     text = UI_GetBotNameByNumber(value);
  1169.  
  1170.     UI_DrawText (rect->x, rect->y, font, scale, color, text, 0, 0 );
  1171. }
  1172.  
  1173. static void UI_DrawBotSkill(rectDef_t *rect, qhandle_t font, float scale, vec4_t color ) 
  1174. {
  1175.     if (uiInfo.skillIndex < 0 || uiInfo.skillIndex >= numSkillLevels) 
  1176.         return;
  1177.  
  1178.     UI_DrawText(rect->x, rect->y, font, scale, color, skillLevels[uiInfo.skillIndex], 0, 0 );
  1179. }
  1180.  
  1181. static void UI_DrawRedBlue(rectDef_t *rect, qhandle_t font, float scale, vec4_t color ) 
  1182. {
  1183.     UI_DrawText (rect->x, rect->y, font, scale, color, (uiInfo.redBlue == 0) ? "Red" : "Blue", 0, 0 );
  1184. }
  1185.  
  1186. static void UI_DrawCrosshair(rectDef_t *rect, float scale, vec4_t color) {
  1187.      trap_R_SetColor( color );
  1188.     if (uiInfo.currentCrosshair < 0 || uiInfo.currentCrosshair >= NUM_CROSSHAIRS) {
  1189.         uiInfo.currentCrosshair = 0;
  1190.     }
  1191.     UI_DrawHandlePic( rect->x, rect->y, 24, 24, uiInfo.uiDC.Assets.crosshairShader[uiInfo.currentCrosshair]);
  1192.      trap_R_SetColor( NULL );
  1193. }
  1194.  
  1195. /*
  1196. ===============
  1197. UI_BuildPlayerList
  1198. ===============
  1199. */
  1200. static void UI_BuildPlayerList() 
  1201. {
  1202.     uiClientState_t    cs;
  1203.     int                n, count, team, team2, playerTeamNumber;
  1204.     char            info[MAX_INFO_STRING];
  1205.  
  1206.     trap_GetClientState( &cs );
  1207.     trap_GetConfigString( CS_PLAYERS + cs.clientNum, info, MAX_INFO_STRING );
  1208.     uiInfo.playerNumber = cs.clientNum;
  1209.     uiInfo.teamLeader = atoi(Info_ValueForKey(info, "tl"));
  1210.     team = atoi(Info_ValueForKey(info, "t"));
  1211.     trap_GetConfigString( CS_SERVERINFO, info, sizeof(info) );
  1212.     count = atoi( Info_ValueForKey( info, "sv_maxclients" ) );
  1213.     uiInfo.playerCount = 0;
  1214.     uiInfo.myTeamCount = 0;
  1215.     playerTeamNumber = 0;
  1216.     
  1217.     for( n = 0; n < count; n++ ) 
  1218.     {
  1219.         trap_GetConfigString( CS_PLAYERS + n, info, MAX_INFO_STRING );
  1220.  
  1221.         if (info[0]) 
  1222.         {
  1223.             Com_sprintf ( uiInfo.playerNames[uiInfo.playerCount], 4, "%2d", n );
  1224.             Q_strncpyz( uiInfo.playerNames[uiInfo.playerCount] + 2, Info_ValueForKey( info, "n" ), MAX_NAME_LENGTH );
  1225.             Q_CleanStr( uiInfo.playerNames[uiInfo.playerCount] + 2 );
  1226.             uiInfo.playerCount++;
  1227.             team2 = atoi(Info_ValueForKey(info, "t"));
  1228.             
  1229.             if (team2 == team) 
  1230.             {
  1231.                 Q_strncpyz( uiInfo.teamNames[uiInfo.myTeamCount], Info_ValueForKey( info, "n" ), MAX_NAME_LENGTH );
  1232.                 Q_CleanStr( uiInfo.teamNames[uiInfo.myTeamCount] );
  1233.                 uiInfo.teamClientNums[uiInfo.myTeamCount] = n;
  1234.  
  1235.                 if (uiInfo.playerNumber == n) 
  1236.                 {
  1237.                     playerTeamNumber = uiInfo.myTeamCount;
  1238.                 }
  1239.  
  1240.                 uiInfo.myTeamCount++;
  1241.             }
  1242.         }
  1243.     }
  1244.  
  1245.     if (!uiInfo.teamLeader) {
  1246.         trap_Cvar_Set("cg_selectedPlayer", va("%d", playerTeamNumber));
  1247.     }
  1248.  
  1249.     n = trap_Cvar_VariableValue("cg_selectedPlayer");
  1250.     if (n < 0 || n > uiInfo.myTeamCount) {
  1251.         n = 0;
  1252.     }
  1253.     if (n < uiInfo.myTeamCount) {
  1254.         trap_Cvar_Set("cg_selectedPlayerName", uiInfo.teamNames[n]);
  1255.     }
  1256. }
  1257.  
  1258.  
  1259. static void UI_DrawSelectedPlayer(rectDef_t *rect, qhandle_t font, float scale, vec4_t color ) 
  1260. {
  1261.     if (uiInfo.uiDC.realTime > uiInfo.playerRefresh) 
  1262.     {
  1263.         uiInfo.playerRefresh = uiInfo.uiDC.realTime + 3000;
  1264.         UI_BuildPlayerList();
  1265.     }
  1266.  
  1267.     UI_DrawText (rect->x, rect->y, font, scale, color, (uiInfo.teamLeader) ? UI_Cvar_VariableString("cg_selectedPlayerName") : UI_Cvar_VariableString("name") , 0, 0 );
  1268. }
  1269.  
  1270. static void UI_DrawServerRefreshDate(rectDef_t *rect, qhandle_t font, float scale, vec4_t color ) 
  1271. {
  1272.     if (uiInfo.serverStatus.refreshActive) 
  1273.     {
  1274.         vec4_t lowLight, newColor;
  1275.         lowLight[0] = 0.8 * color[0]; 
  1276.         lowLight[1] = 0.8 * color[1]; 
  1277.         lowLight[2] = 0.8 * color[2]; 
  1278.         lowLight[3] = 0.8 * color[3]; 
  1279.         LerpColor(color,lowLight,newColor,0.5+0.5*sin(uiInfo.uiDC.realTime / PULSE_DIVISOR));
  1280.         UI_DrawText (rect->x, rect->y, font, scale, newColor, va("Getting info for %d servers (ESC to cancel)", trap_LAN_GetServerCount(ui_netSource.integer)), 0, 0 );
  1281.     } 
  1282.     else 
  1283.     {
  1284.         char buff[64];
  1285.         Q_strncpyz(buff, UI_Cvar_VariableString(va("ui_lastServerRefresh_%i", ui_netSource.integer)), 64);
  1286.         UI_DrawText (rect->x, rect->y, font, scale, color, va("Refresh Time: %s", buff), 0, 0 );
  1287.     }
  1288. }
  1289.  
  1290. static void UI_DrawServerMOTD(rectDef_t *rect, float scale, vec4_t color) {
  1291.     if (uiInfo.serverStatus.motdLen) {
  1292.         float maxX;
  1293.      
  1294.         if (uiInfo.serverStatus.motdWidth == -1) {
  1295.             uiInfo.serverStatus.motdWidth = 0;
  1296.             uiInfo.serverStatus.motdPaintX = rect->x + 1;
  1297.             uiInfo.serverStatus.motdPaintX2 = -1;
  1298.         }
  1299.  
  1300.         if (uiInfo.serverStatus.motdOffset > uiInfo.serverStatus.motdLen) {
  1301.             uiInfo.serverStatus.motdOffset = 0;
  1302.             uiInfo.serverStatus.motdPaintX = rect->x + 1;
  1303.             uiInfo.serverStatus.motdPaintX2 = -1;
  1304.         }
  1305.  
  1306.         if (uiInfo.uiDC.realTime > uiInfo.serverStatus.motdTime) 
  1307.         {
  1308.             uiInfo.serverStatus.motdTime = uiInfo.uiDC.realTime + 10;
  1309.             if (uiInfo.serverStatus.motdPaintX <= rect->x + 2) 
  1310.             {
  1311.                 if (uiInfo.serverStatus.motdOffset < uiInfo.serverStatus.motdLen) 
  1312.                 {
  1313.                     uiInfo.serverStatus.motdPaintX += trap_R_GetTextWidth ( &uiInfo.serverStatus.motd[uiInfo.serverStatus.motdOffset], uiInfo.uiDC.Assets.defaultFont, scale, 1 ) - 1;
  1314.                     uiInfo.serverStatus.motdOffset++;
  1315.                 } 
  1316.                 else 
  1317.                 {
  1318.                     uiInfo.serverStatus.motdOffset = 0;
  1319.                     if (uiInfo.serverStatus.motdPaintX2 >= 0) 
  1320.                     {
  1321.                         uiInfo.serverStatus.motdPaintX = uiInfo.serverStatus.motdPaintX2;
  1322.                     } 
  1323.                     else 
  1324.                     {
  1325.                         uiInfo.serverStatus.motdPaintX = rect->x + rect->w - 2;
  1326.                     }
  1327.                     uiInfo.serverStatus.motdPaintX2 = -1;
  1328.                 }
  1329.             } 
  1330.             else 
  1331.             {
  1332.                 //serverStatus.motdPaintX--;
  1333.                 uiInfo.serverStatus.motdPaintX -= 2;
  1334.                 if (uiInfo.serverStatus.motdPaintX2 >= 0) {
  1335.                     //serverStatus.motdPaintX2--;
  1336.                     uiInfo.serverStatus.motdPaintX2 -= 2;
  1337.                 }
  1338.             }
  1339.         }
  1340.  
  1341.         maxX = rect->x + rect->w - 2;
  1342. //        Text_Paint_Limit(&maxX, uiInfo.serverStatus.motdPaintX, rect->y + rect->h - 3, scale, color, &uiInfo.serverStatus.motd[uiInfo.serverStatus.motdOffset], 0, 0, NULL ); 
  1343.         if (uiInfo.serverStatus.motdPaintX2 >= 0) 
  1344.         {
  1345. //            float maxX2 = rect->x + rect->w - 2;
  1346. //            Text_Paint_Limit(&maxX2, uiInfo.serverStatus.motdPaintX2, rect->y + rect->h - 3, scale, color, uiInfo.serverStatus.motd, 0, uiInfo.serverStatus.motdOffset, NULL ); 
  1347.         }
  1348.         if (uiInfo.serverStatus.motdOffset && maxX > 0) {
  1349.             // if we have an offset ( we are skipping the first part of the string ) and we fit the string
  1350.             if (uiInfo.serverStatus.motdPaintX2 == -1) {
  1351.                         uiInfo.serverStatus.motdPaintX2 = rect->x + rect->w - 2;
  1352.             }
  1353.         } else {
  1354.             uiInfo.serverStatus.motdPaintX2 = -1;
  1355.         }
  1356.  
  1357.     }
  1358. }
  1359.  
  1360. static void UI_DrawKeyBindStatus(rectDef_t *rect, qhandle_t font, float scale, vec4_t color ) 
  1361. {
  1362.     if (Display_KeyBindPending()) 
  1363.     {
  1364.         UI_DrawText (rect->x, rect->y, font, scale, color, "Waiting for new key... Press ESCAPE to cancel", 0, 0 );
  1365.     } 
  1366.     else 
  1367.     {
  1368.         UI_DrawText (rect->x, rect->y, font, scale, color, "Press ENTER or CLICK to change, Press BACKSPACE to clear", 0, 0 );
  1369.     }
  1370. }
  1371.  
  1372. static void UI_DrawGLInfo(rectDef_t *rect, qhandle_t font, float scale, vec4_t color ) 
  1373. {
  1374.     char * eptr;
  1375.     char buff[4096];
  1376.     const char *lines[64];
  1377.     int y, numLines, i;
  1378.  
  1379.     UI_DrawText (rect->x + 2, rect->y, font, scale, color, va("VENDOR: %s", uiInfo.uiDC.glconfig.vendor_string), 30, 0 );
  1380.     UI_DrawText (rect->x + 2, rect->y + 15, font, scale, color, va("VERSION: %s: %s", uiInfo.uiDC.glconfig.version_string,uiInfo.uiDC.glconfig.renderer_string), 30, 0 );
  1381.     UI_DrawText (rect->x + 2, rect->y + 30, font, scale, color, va ("PIXELFORMAT: color(%d-bits) Z(%d-bits) stencil(%d-bits)", uiInfo.uiDC.glconfig.colorBits, uiInfo.uiDC.glconfig.depthBits, uiInfo.uiDC.glconfig.stencilBits), 30, 0);
  1382.  
  1383.     // build null terminated extension strings
  1384.     Q_strncpyz(buff, uiInfo.uiDC.glconfig.extensions_string, 4096);
  1385.     eptr = buff;
  1386.     y = rect->y + 45;
  1387.     numLines = 0;
  1388.     while ( y < rect->y + rect->h && *eptr )
  1389.     {
  1390.         while ( *eptr && *eptr == ' ' )
  1391.             *eptr++ = '\0';
  1392.  
  1393.         // track start of valid string
  1394.         if (*eptr && *eptr != ' ') {
  1395.             lines[numLines++] = eptr;
  1396.         }
  1397.  
  1398.         while ( *eptr && *eptr != ' ' )
  1399.             eptr++;
  1400.     }
  1401.  
  1402.     i = 0;
  1403.     while (i < numLines) 
  1404.     {
  1405.         UI_DrawText (rect->x + 2, y, font, scale, color, lines[i++], 20, 0 );
  1406.         
  1407.         if (i < numLines) 
  1408.         {
  1409.             UI_DrawText(rect->x + rect->w / 2, y, font, scale, color, lines[i++], 20, 0 );
  1410.         
  1411.         }
  1412.         y += 10;
  1413.  
  1414.         if (y > rect->y + rect->h - 11) 
  1415.         {
  1416.             break;
  1417.         }
  1418.     }
  1419.  
  1420.  
  1421. }
  1422.  
  1423. /*
  1424. =================
  1425. UI_Version
  1426. =================
  1427. */
  1428. static void UI_Version(rectDef_t *rect, float scale, vec4_t color) 
  1429. {
  1430.     int width;
  1431.     
  1432.     width = trap_R_GetTextWidth ( Q3_VERSION, uiInfo.uiDC.Assets.defaultFont, scale, 0 );
  1433.  
  1434.     UI_DrawText (rect->x - width, rect->y, uiInfo.uiDC.Assets.defaultFont, scale, color, Q3_VERSION, 0, 0 );
  1435. }
  1436.  
  1437. // FIXME: table drive
  1438. //
  1439. static void UI_OwnerDraw(float x, float y, float w, float h, float text_x, float text_y, int ownerDraw, int ownerDrawFlags, int align, float special, qhandle_t font, float scale, vec4_t color, qhandle_t shader, int textStyle, const char* param ) 
  1440. {
  1441.     rectDef_t rect;
  1442.  
  1443.     rect.x = x + text_x;
  1444.     rect.y = y + text_y;
  1445.     rect.w = w;
  1446.     rect.h = h;
  1447.  
  1448.     switch (ownerDraw) 
  1449.     {
  1450.         case UI_OUTFITTING_SLOT_RENDER:
  1451.             UI_DrawOutfittingSlotRender ( &rect, atoi ( param ));
  1452.             break;
  1453.  
  1454.         case UI_OUTFITTING_SLOT_NAME:
  1455.             UI_DrawOutfittingSlotName ( &rect, font, scale, color, atoi ( param ) );
  1456.             break;        
  1457.  
  1458.         case UI_OUTFITTING_SLOT_BACKGROUND:
  1459.             UI_DrawOutfittingBackground ( &rect, color, atoi ( param ) );
  1460.             break;
  1461.  
  1462.         case UI_PLAYERMODEL:
  1463.             UI_DrawPlayerModel(&rect);
  1464.             break;
  1465.  
  1466.         case UI_PREVIEWCINEMATIC:
  1467.             UI_DrawPreviewCinematic(&rect, scale, color);
  1468.             break;
  1469.         
  1470.         case UI_GAMETYPE:
  1471.             UI_DrawGameType(&rect, font, scale, color );
  1472.             break;
  1473.  
  1474.         case UI_OBJECTIVE_PHOTOS:    
  1475.             UI_DrawObjectivePhotos (&rect, font, scale, color );
  1476.             break;
  1477.  
  1478.         case UI_NETGAMETYPE:
  1479.             UI_DrawNetGameType(&rect, font, scale, color );
  1480.             break;
  1481.  
  1482.         case UI_JOINGAMETYPE:
  1483.             UI_DrawJoinGameType(&rect, font, scale, color );
  1484.             break;
  1485.  
  1486.         case UI_MAPPREVIEW:
  1487.             UI_DrawMapPreview(&rect, scale, color, qtrue);
  1488.             break;
  1489.     
  1490.         case UI_MAPCINEMATIC:
  1491.       UI_DrawMapCinematic(&rect, scale, color, qfalse);
  1492.       break;
  1493.     case UI_STARTMAPCINEMATIC:
  1494.       UI_DrawMapCinematic(&rect, scale, color, qtrue);
  1495.       break;
  1496.         
  1497.         case UI_SKILL:
  1498.             UI_DrawSkill(&rect, font, scale, color );
  1499.             break;
  1500.  
  1501.         case UI_REDTEAM_IDENTITY:
  1502.             UI_DrawTeamIdentity ( &rect, TEAM_RED, atoi(param) );
  1503.             break;
  1504.  
  1505.         case UI_BLUETEAM_IDENTITY:
  1506.             UI_DrawTeamIdentity ( &rect, TEAM_BLUE, atoi(param) );
  1507.             break;
  1508.         
  1509.         case UI_NETSOURCE:
  1510.             UI_DrawNetSource(&rect, font, scale, color );
  1511.             break;
  1512.         
  1513.     case UI_NETMAPPREVIEW:
  1514.       UI_DrawNetMapPreview(&rect, scale, color);
  1515.       break;
  1516.     case UI_NETMAPCINEMATIC:
  1517.       UI_DrawNetMapCinematic(&rect, scale, color);
  1518.       break;
  1519.         
  1520.         case UI_NETFILTER:
  1521.             UI_DrawNetFilter(&rect, font, scale, color );
  1522.             break;
  1523.         case UI_ALLMAPS_SELECTION:
  1524.             UI_DrawAllMapsSelection(&rect, font, scale, color, textStyle, qtrue);
  1525.             break;
  1526.         case UI_MAPS_SELECTION:
  1527.             UI_DrawAllMapsSelection(&rect, font, scale, color, textStyle, qfalse);
  1528.             break;
  1529.         case UI_BOTNAME:
  1530.             UI_DrawBotName(&rect, font, scale, color );
  1531.             break;
  1532.         case UI_BOTSKILL:
  1533.             UI_DrawBotSkill(&rect, font, scale, color );
  1534.             break;
  1535.         case UI_REDBLUE:
  1536.             UI_DrawRedBlue(&rect, font, scale, color );
  1537.             break;
  1538.         case UI_CROSSHAIR:
  1539.             UI_DrawCrosshair(&rect, scale, color);
  1540.             break;
  1541.         case UI_SELECTEDPLAYER:
  1542.             UI_DrawSelectedPlayer(&rect, font, scale, color );
  1543.             break;
  1544.         case UI_SERVERREFRESHDATE:
  1545.             UI_DrawServerRefreshDate(&rect, font, scale, color );
  1546.             break;
  1547.         case UI_SERVERMOTD:
  1548.             UI_DrawServerMOTD(&rect, scale, color);
  1549.             break;
  1550.         case UI_GLINFO:
  1551.             UI_DrawGLInfo(&rect, font, scale, color );
  1552.             break;
  1553.         case UI_VERSIONDOWNLOAD_PROGRESS:
  1554.             UI_DrawVersionDownloadProgress(&rect, font, scale, color );
  1555.             break;
  1556.         default:
  1557.             break;
  1558.     }
  1559. }
  1560.  
  1561. static void UI_DrawVersionDownloadProgress(rectDef_t *rect, qhandle_t font, float scale, vec4_t color )
  1562. {
  1563.     // Add code to show loading progress
  1564.     UI_DrawText (rect->x, rect->y, font, scale, color, va("Progress: %d %",90),0,0);
  1565. }
  1566.  
  1567. static qboolean UI_OwnerDrawDisabled ( int flags, const char* param )
  1568. {    
  1569.     return qfalse;
  1570. }
  1571.  
  1572. static qboolean UI_OwnerDrawVisible ( int flags, const char* param ) 
  1573. {
  1574.     qboolean vis = qtrue;
  1575.  
  1576.     while (vis && flags) 
  1577.     {
  1578.         if (flags & UI_SHOW_LEADER) 
  1579.         {
  1580.             // these need to show when this client can give orders to a player or a group
  1581.             if (!uiInfo.teamLeader) 
  1582.             {
  1583.                 vis = qfalse;
  1584.             } 
  1585.             else 
  1586.             {
  1587.                 // if showing yourself
  1588.                 if (ui_selectedPlayer.integer < uiInfo.myTeamCount && uiInfo.teamClientNums[ui_selectedPlayer.integer] == uiInfo.playerNumber) 
  1589.                 {                 
  1590.                     vis = qfalse;
  1591.                 }
  1592.             }
  1593.             flags &= ~UI_SHOW_LEADER;
  1594.         } 
  1595.  
  1596.         if (flags & UI_SHOW_NOTLEADER) 
  1597.         {
  1598.             // these need to show when this client is assigning their own status or they are NOT the leader
  1599.             if (uiInfo.teamLeader) {
  1600.                 // if not showing yourself
  1601.                 if (!(ui_selectedPlayer.integer < uiInfo.myTeamCount && uiInfo.teamClientNums[ui_selectedPlayer.integer] == uiInfo.playerNumber)) { 
  1602.                     vis = qfalse;
  1603.                 }
  1604.                 // these need to show when this client can give orders to a player or a group
  1605.             }
  1606.             flags &= ~UI_SHOW_NOTLEADER;
  1607.         } 
  1608.         if (flags & UI_SHOW_FAVORITESERVERS) {
  1609.             // this assumes you only put this type of display flag on something showing in the proper context
  1610.             if (ui_netSource.integer != AS_FAVORITES) {
  1611.                 vis = qfalse;
  1612.             }
  1613.             flags &= ~UI_SHOW_FAVORITESERVERS;
  1614.         } 
  1615.         if (flags & UI_SHOW_NOTFAVORITESERVERS) {
  1616.             // this assumes you only put this type of display flag on something showing in the proper context
  1617.             if (ui_netSource.integer == AS_FAVORITES) {
  1618.                 vis = qfalse;
  1619.             }
  1620.             flags &= ~UI_SHOW_NOTFAVORITESERVERS;
  1621.         } 
  1622.         if (flags & UI_SHOW_ANYTEAMGAME) 
  1623.         {
  1624.             if ( !bg_gametypeData[ui_gameType.integer].teams ) 
  1625.             {
  1626.                 vis = qfalse;
  1627.             }
  1628.             flags &= ~UI_SHOW_ANYTEAMGAME;
  1629.         } 
  1630.         
  1631.         if (flags & UI_SHOW_ANYNONTEAMGAME) 
  1632.         {
  1633.             if ( bg_gametypeData[ui_gameType.integer].teams ) 
  1634.             {
  1635.                 vis = qfalse;
  1636.             }
  1637.             
  1638.             flags &= ~UI_SHOW_ANYNONTEAMGAME;
  1639.         } 
  1640.         
  1641.         if (flags & UI_SHOW_NETANYTEAMGAME) 
  1642.         {
  1643.             if ( !bg_gametypeData[ui_netGameType.integer].teams ) 
  1644.             {
  1645.                 vis = qfalse;
  1646.             }
  1647.  
  1648.             flags &= ~UI_SHOW_NETANYTEAMGAME;
  1649.         } 
  1650.         
  1651.         if (flags & UI_SHOW_NETANYNONTEAMGAME) 
  1652.         {
  1653.             if ( bg_gametypeData[ui_netGameType.integer].teams ) 
  1654.             {
  1655.                 vis = qfalse;
  1656.             }
  1657.             flags &= ~UI_SHOW_NETANYNONTEAMGAME;
  1658.         } 
  1659.         if (flags & UI_SHOW_NEWHIGHSCORE) {
  1660.             if (uiInfo.newHighScoreTime < uiInfo.uiDC.realTime) {
  1661.                 vis = qfalse;
  1662.             } else {
  1663.                 if (uiInfo.soundHighScore) {
  1664.                     if (trap_Cvar_VariableValue("sv_killserver") == 0) {
  1665.                         // wait on server to go down before playing sound
  1666.                         uiInfo.soundHighScore = qfalse;
  1667.                     }
  1668.                 }
  1669.             }
  1670.             flags &= ~UI_SHOW_NEWHIGHSCORE;
  1671.         } 
  1672.         if (flags & UI_SHOW_NEWBESTTIME) {
  1673.             if (uiInfo.newBestTime < uiInfo.uiDC.realTime) {
  1674.                 vis = qfalse;
  1675.             }
  1676.             flags &= ~UI_SHOW_NEWBESTTIME;
  1677.         } 
  1678.         if (flags & UI_SHOW_DEMOAVAILABLE) {
  1679.             if (!uiInfo.demoAvailable) {
  1680.                 vis = qfalse;
  1681.             }
  1682.             flags &= ~UI_SHOW_DEMOAVAILABLE;
  1683.         } else {
  1684.             flags = 0;
  1685.         }
  1686.     }
  1687.   return vis;
  1688. }
  1689.  
  1690. static qboolean UI_GameType_HandleKey(int flags, float *special, int key, qboolean resetMap) 
  1691. {
  1692.     if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) 
  1693.     {
  1694.         int oldCount = UI_MapCountByGameType();
  1695.  
  1696.         // hard coded mess here
  1697.         if (key == K_MOUSE2) 
  1698.         {
  1699.             ui_gameType.integer--;
  1700.             if (ui_gameType.integer == 2) 
  1701.             {
  1702.                 ui_gameType.integer = 1;
  1703.             } 
  1704.             else if (ui_gameType.integer < 2) 
  1705.             {
  1706.                 ui_gameType.integer = bg_gametypeCount - 1;
  1707.             }
  1708.         } 
  1709.         else 
  1710.         {
  1711.             ui_gameType.integer++;
  1712.             if (ui_gameType.integer >= bg_gametypeCount ) 
  1713.             {
  1714.                 ui_gameType.integer = 1;
  1715.             } 
  1716.             else if (ui_gameType.integer == 2) 
  1717.             {
  1718.                 ui_gameType.integer = 3;
  1719.             }
  1720.         }
  1721.     
  1722.         trap_Cvar_Set("ui_gameType", va("%d", ui_gameType.integer));
  1723.         
  1724.         if (resetMap && oldCount != UI_MapCountByGameType()) 
  1725.         {
  1726.               trap_Cvar_Set( "ui_currentMap", "0");
  1727.             Menu_SetFeederSelection(NULL, FEEDER_MAPS, 0, NULL);
  1728.         }
  1729.  
  1730.         return qtrue;
  1731.     }
  1732.     
  1733.     return qfalse;
  1734. }
  1735.  
  1736. static qboolean UI_NetGameType_HandleKey(int flags, float *special, int key) 
  1737. {
  1738.     if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) 
  1739.     {
  1740.         int oldMapIndex;
  1741.         int actual;
  1742.  
  1743.         if (key == K_MOUSE2) 
  1744.         {
  1745.             ui_netGameType.integer--;
  1746.         } 
  1747.         else 
  1748.         {
  1749.             ui_netGameType.integer++;
  1750.         }
  1751.  
  1752.         if (ui_netGameType.integer < 0) 
  1753.         {
  1754.             ui_netGameType.integer = bg_gametypeCount - 1;
  1755.         } 
  1756.         else if (ui_netGameType.integer >= bg_gametypeCount) 
  1757.         {
  1758.             ui_netGameType.integer = 0;
  1759.         } 
  1760.  
  1761.         if( uiInfo.mapCount )
  1762.         {
  1763.             oldMapIndex = ui_currentNetMap.integer;
  1764.         }
  1765.         else
  1766.         {
  1767.             oldMapIndex = 0;
  1768.         }
  1769.  
  1770.           trap_Cvar_Set( "ui_netGameType", va("%d", ui_netGameType.integer));
  1771.           trap_Cvar_Set( "ui_actualnetGameType", va("%d", ui_netGameType.integer));
  1772.         trap_Cvar_Set( "ui_gtRespawnType", va("%d", bg_gametypeData[ui_netGameType.integer].respawnType ) );
  1773.         trap_Cvar_Set( "ui_gtPickupsDisabled", va("%d", bg_gametypeData[ui_netGameType.integer].pickupsDisabled ) );
  1774.  
  1775.         UI_SelectedMap ( 0, &actual );
  1776.         ui_currentNetMap.integer = actual;
  1777.         trap_Cvar_Set("ui_currentNetMap", va("%d",actual));
  1778.         trap_Cvar_Set("ui_currentNetMapName", uiInfo.mapList[actual].mapLoadName );
  1779.  
  1780.         UI_MapCountByGameType();
  1781.         Menu_SetFeederSelection(NULL, FEEDER_ALLMAPS, 0, NULL);
  1782.  
  1783.         if ( oldMapIndex > 0)
  1784.         {
  1785.             if ( uiInfo.mapList[oldMapIndex].active )
  1786.             {
  1787.                 Menu_SetFeederSelection ( NULL, FEEDER_ALLMAPS, UI_GetIndexFromSelection(oldMapIndex), NULL );
  1788.             }
  1789.         }        
  1790.         
  1791.         return qtrue;
  1792.     }
  1793.  
  1794.     return qfalse;
  1795. }
  1796.  
  1797. static qboolean UI_JoinGameType_HandleKey(int flags, float *special, int key) 
  1798. {
  1799.     if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) 
  1800.     {
  1801.         if (key == K_MOUSE2) 
  1802.         {
  1803.             ui_joinGameType.integer--;
  1804.         } 
  1805.         else 
  1806.         {
  1807.             ui_joinGameType.integer++;
  1808.         }
  1809.  
  1810.         if (ui_joinGameType.integer < 0) 
  1811.         {
  1812.             ui_joinGameType.integer = bg_gametypeCount;
  1813.         } 
  1814.         else if (ui_joinGameType.integer > bg_gametypeCount ) 
  1815.         {
  1816.             ui_joinGameType.integer = 0;
  1817.         }
  1818.  
  1819.         trap_Cvar_Set( "ui_joinGameType", va("%d", ui_joinGameType.integer));
  1820.         UI_BuildServerDisplayList(qtrue);
  1821.         return qtrue;
  1822.     }
  1823.     return qfalse;
  1824. }
  1825.  
  1826.  
  1827.  
  1828. static qboolean UI_Skill_HandleKey(int flags, float *special, int key) 
  1829. {
  1830.     if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) 
  1831.     {
  1832.         int i = trap_Cvar_VariableValue( "g_botSkill" );
  1833.  
  1834.         if (key == K_MOUSE2) 
  1835.         {
  1836.             i--;
  1837.         } 
  1838.         else 
  1839.         {
  1840.             i++;
  1841.         }
  1842.  
  1843.         if (i < 1) 
  1844.         {
  1845.             i = numSkillLevels;
  1846.         } 
  1847.         else if (i > numSkillLevels) 
  1848.         {
  1849.             i = 1;
  1850.         }
  1851.  
  1852.         trap_Cvar_Set("g_botSkill", va("%i", i));
  1853.         
  1854.         return qtrue;
  1855.     }
  1856.     
  1857.     return qfalse;
  1858. }
  1859.  
  1860. static qboolean UI_NetSource_HandleKey(int flags, float *special, int key) {
  1861.   if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
  1862.         
  1863.         if (key == K_MOUSE2) {
  1864.             ui_netSource.integer--;
  1865.         } else {
  1866.             ui_netSource.integer++;
  1867.         }
  1868.     
  1869.         if (ui_netSource.integer >= numNetSources) {
  1870.       ui_netSource.integer = 0;
  1871.     } else if (ui_netSource.integer < 0) {
  1872.       ui_netSource.integer = numNetSources - 1;
  1873.         }
  1874.  
  1875.         UI_BuildServerDisplayList(qtrue);
  1876.         if (ui_netSource.integer != AS_GLOBAL) {
  1877.             UI_StartServerRefresh(qtrue);
  1878.         }
  1879.       trap_Cvar_Set( "ui_netSource", va("%d", ui_netSource.integer));
  1880.     return qtrue;
  1881.   }
  1882.   return qfalse;
  1883. }
  1884.  
  1885. static qboolean UI_NetFilter_HandleKey(int flags, float *special, int key) {
  1886.   if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
  1887.  
  1888.         if (key == K_MOUSE2) {
  1889.             ui_serverFilterType.integer--;
  1890.         } else {
  1891.             ui_serverFilterType.integer++;
  1892.         }
  1893.  
  1894.     if (ui_serverFilterType.integer >= numServerFilters) {
  1895.       ui_serverFilterType.integer = 0;
  1896.     } else if (ui_serverFilterType.integer < 0) {
  1897.       ui_serverFilterType.integer = numServerFilters - 1;
  1898.         }
  1899.         UI_BuildServerDisplayList(qtrue);
  1900.     return qtrue;
  1901.   }
  1902.   return qfalse;
  1903. }
  1904.  
  1905. static qboolean UI_BotName_HandleKey(int flags, float *special, int key) 
  1906. {
  1907.     if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) 
  1908.     {
  1909.         int value = uiInfo.botIndex;
  1910.  
  1911.         if (key == K_MOUSE2) 
  1912.         {
  1913.             value--;
  1914.         } 
  1915.         else 
  1916.         {
  1917.             value++;
  1918.         }
  1919.  
  1920.         if (value >= UI_GetNumBots() ) 
  1921.         {
  1922.             value = 0;
  1923.         } 
  1924.         else if (value < 0) 
  1925.         {
  1926.             value = UI_GetNumBots() - 1;
  1927.         }
  1928.         
  1929.         uiInfo.botIndex = value;
  1930.         
  1931.         return qtrue;
  1932.     }
  1933.     
  1934.     return qfalse;
  1935. }
  1936.  
  1937. static qboolean UI_BotSkill_HandleKey(int flags, float *special, int key) {
  1938.   if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
  1939.         if (key == K_MOUSE2) {
  1940.             uiInfo.skillIndex--;
  1941.         } else {
  1942.             uiInfo.skillIndex++;
  1943.         }
  1944.         if (uiInfo.skillIndex >= numSkillLevels) {
  1945.             uiInfo.skillIndex = 0;
  1946.         } else if (uiInfo.skillIndex < 0) {
  1947.             uiInfo.skillIndex = numSkillLevels-1;
  1948.         }
  1949.     return qtrue;
  1950.   }
  1951.     return qfalse;
  1952. }
  1953.  
  1954. static qboolean UI_RedBlue_HandleKey(int flags, float *special, int key) {
  1955.   if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
  1956.         uiInfo.redBlue ^= 1;
  1957.         return qtrue;
  1958.     }
  1959.     return qfalse;
  1960. }
  1961.  
  1962. static qboolean UI_Crosshair_HandleKey(int flags, float *special, int key) {
  1963.   if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
  1964.         if (key == K_MOUSE2) {
  1965.             uiInfo.currentCrosshair--;
  1966.         } else {
  1967.             uiInfo.currentCrosshair++;
  1968.         }
  1969.  
  1970.         if (uiInfo.currentCrosshair >= NUM_CROSSHAIRS) {
  1971.             uiInfo.currentCrosshair = 0;
  1972.         } else if (uiInfo.currentCrosshair < 0) {
  1973.             uiInfo.currentCrosshair = NUM_CROSSHAIRS - 1;
  1974.         }
  1975.         trap_Cvar_Set("cg_drawCrosshair", va("%d", uiInfo.currentCrosshair)); 
  1976.         return qtrue;
  1977.     }
  1978.     return qfalse;
  1979. }
  1980.  
  1981. static qboolean UI_OutfittingSlot_HandleKey ( int slot, int key )
  1982. {
  1983.     weapon_t weapon;
  1984.  
  1985.     switch ( key )
  1986.     {
  1987.         case K_MOUSE1:
  1988.         case K_ENTER:
  1989.         case K_RIGHTARROW:
  1990.  
  1991.             // Nothing to cycle?
  1992.             if ( bg_outfittings[uiInfo.outfittingItemGroup].items[slot] == -1 )
  1993.             {
  1994.                 break;
  1995.             }
  1996.  
  1997.             do
  1998.             {
  1999.                 if ( uiInfo.outfittingItemGroup != 0 )
  2000.                 {
  2001.                     memcpy ( &bg_outfittings[0].items, &bg_outfittings[uiInfo.outfittingItemGroup].items, sizeof(bg_outfittings[0].items) );
  2002.                     Menu_SetFeederSelection(NULL, FEEDER_OUTFITTING_TEMPLATES, 0, "ingame_outfitting");
  2003.                 }
  2004.  
  2005.                 bg_outfittings[uiInfo.outfittingItemGroup].items[slot]++;
  2006.                 if ( bg_outfittingGroups[slot][bg_outfittings[uiInfo.outfittingItemGroup].items[slot]] == -1 )
  2007.                 {
  2008.                     bg_outfittings[uiInfo.outfittingItemGroup].items[slot] = 0;
  2009.                 }
  2010.  
  2011.                 if ( bg_itemlist[bg_outfittingGroups[slot][bg_outfittings[uiInfo.outfittingItemGroup].items[slot]]].giType != IT_WEAPON )
  2012.                 {
  2013.                     break;
  2014.                 }
  2015.  
  2016.                 weapon = bg_itemlist[bg_outfittingGroups[slot][bg_outfittings[uiInfo.outfittingItemGroup].items[slot]]].giTag;
  2017.             }
  2018.             while ( !BG_IsWeaponAvailableForOutfitting ( weapon, 2 ) );
  2019.  
  2020.             return qtrue;
  2021.  
  2022.         case K_MOUSE2:
  2023.         case K_SPACE:
  2024.         case K_LEFTARROW:
  2025.  
  2026.             // Nothing to cycle?
  2027.             if ( bg_outfittings[uiInfo.outfittingItemGroup].items[slot] == -1 )
  2028.             {
  2029.                 break;
  2030.             }
  2031.  
  2032.             do
  2033.             {
  2034.                 if ( uiInfo.outfittingItemGroup != 0 )
  2035.                 {
  2036.                     memcpy ( &bg_outfittings[0].items, &bg_outfittings[uiInfo.outfittingItemGroup].items, sizeof(bg_outfittings[0].items) );
  2037.                     Menu_SetFeederSelection(NULL, FEEDER_OUTFITTING_TEMPLATES, 0, "ingame_outfitting");
  2038.                 }
  2039.  
  2040.                 bg_outfittings[uiInfo.outfittingItemGroup].items[slot]--;
  2041.                 if ( bg_outfittings[uiInfo.outfittingItemGroup].items[slot] < 0 )
  2042.                 {
  2043.                     bg_outfittings[uiInfo.outfittingItemGroup].items[slot] = MAX_OUTFITTING_GROUPITEM-1;
  2044.                     // Find the first valid one starting from the back
  2045.                     while ( bg_outfittingGroups[slot][bg_outfittings[uiInfo.outfittingItemGroup].items[slot]] == -1 )
  2046.                     {
  2047.                         bg_outfittings[uiInfo.outfittingItemGroup].items[slot]--;
  2048.                     }
  2049.                 }
  2050.  
  2051.                 if ( bg_itemlist[bg_outfittingGroups[slot][bg_outfittings[uiInfo.outfittingItemGroup].items[slot]]].giType != IT_WEAPON )
  2052.                 {
  2053.                     break;
  2054.                 }
  2055.  
  2056.                 weapon = bg_itemlist[bg_outfittingGroups[slot][bg_outfittings[uiInfo.outfittingItemGroup].items[slot]]].giTag;
  2057.             }
  2058.             while ( !BG_IsWeaponAvailableForOutfitting ( weapon, 2 ) );
  2059.  
  2060.             return qtrue;
  2061.     }
  2062.  
  2063.     return qfalse;
  2064. }
  2065.  
  2066. static qboolean UI_SelectedPlayer_HandleKey(int flags, float *special, int key) {
  2067.   if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
  2068.         int selected;
  2069.  
  2070.         UI_BuildPlayerList();
  2071.         if (!uiInfo.teamLeader) {
  2072.             return qfalse;
  2073.         }
  2074.         selected = trap_Cvar_VariableValue("cg_selectedPlayer");
  2075.         
  2076.         if (key == K_MOUSE2) {
  2077.             selected--;
  2078.         } else {
  2079.             selected++;
  2080.         }
  2081.  
  2082.         if (selected > uiInfo.myTeamCount) {
  2083.             selected = 0;
  2084.         } else if (selected < 0) {
  2085.             selected = uiInfo.myTeamCount;
  2086.         }
  2087.  
  2088.         if (selected == uiInfo.myTeamCount) {
  2089.              trap_Cvar_Set( "cg_selectedPlayerName", "Everyone");
  2090.         } else {
  2091.              trap_Cvar_Set( "cg_selectedPlayerName", uiInfo.teamNames[selected]);
  2092.         }
  2093.          trap_Cvar_Set( "cg_selectedPlayer", va("%d", selected));
  2094.     }
  2095.     return qfalse;
  2096. }
  2097.  
  2098.  
  2099. static qboolean UI_OwnerDrawHandleKey ( int ownerDraw, int flags, float *special, int key, const char* param ) 
  2100. {
  2101.     switch (ownerDraw) 
  2102.     {
  2103.         case UI_GAMETYPE:
  2104.             return UI_GameType_HandleKey(flags, special, key, qtrue);
  2105.  
  2106.         case UI_NETGAMETYPE:
  2107.             return UI_NetGameType_HandleKey(flags, special, key);
  2108.  
  2109.         case UI_JOINGAMETYPE:
  2110.             return UI_JoinGameType_HandleKey(flags, special, key);
  2111.  
  2112.         case UI_SKILL:
  2113.             return UI_Skill_HandleKey(flags, special, key);
  2114.  
  2115.         case UI_NETSOURCE:
  2116.             UI_NetSource_HandleKey(flags, special, key);
  2117.             break;
  2118.         
  2119.         case UI_NETFILTER:
  2120.             UI_NetFilter_HandleKey(flags, special, key);
  2121.             break;
  2122.         
  2123.     
  2124.         case UI_BOTNAME:
  2125.             return UI_BotName_HandleKey(flags, special, key);
  2126.  
  2127.         case UI_BOTSKILL:
  2128.             return UI_BotSkill_HandleKey(flags, special, key);
  2129.  
  2130.         case UI_REDBLUE:
  2131.             UI_RedBlue_HandleKey(flags, special, key);
  2132.             break;
  2133.  
  2134.         case UI_CROSSHAIR:
  2135.             UI_Crosshair_HandleKey(flags, special, key);
  2136.             break;
  2137.  
  2138.         case UI_SELECTEDPLAYER:
  2139.             UI_SelectedPlayer_HandleKey(flags, special, key);
  2140.             break;
  2141.         
  2142.         case UI_OUTFITTING_SLOT:
  2143.             UI_OutfittingSlot_HandleKey ( atoi(param), key );
  2144.             break;
  2145.  
  2146.         default:
  2147.             break;
  2148.     }
  2149.  
  2150.     return qfalse;
  2151. }
  2152.  
  2153.  
  2154. static float UI_GetValue(int ownerDraw) {
  2155.   return 0;
  2156. }
  2157.  
  2158. /*
  2159. =================
  2160. UI_ServersQsortCompare
  2161. =================
  2162. */
  2163. static int QDECL UI_ServersQsortCompare( const void *arg1, const void *arg2 ) {
  2164.     return trap_LAN_CompareServers( ui_netSource.integer, uiInfo.serverStatus.sortKey, uiInfo.serverStatus.sortDir, *(int*)arg1, *(int*)arg2);
  2165. }
  2166.  
  2167.  
  2168. /*
  2169. =================
  2170. UI_ServersSort
  2171. =================
  2172. */
  2173. void UI_ServersSort(int column, qboolean force) {
  2174.  
  2175.     if ( !force ) {
  2176.         if ( uiInfo.serverStatus.sortKey == column ) {
  2177.             return;
  2178.         }
  2179.     }
  2180.  
  2181.     uiInfo.serverStatus.sortKey = column;
  2182.     qsort( &uiInfo.serverStatus.displayServers[0], uiInfo.serverStatus.numDisplayServers, sizeof(int), UI_ServersQsortCompare);
  2183. }
  2184. /*
  2185. ===============
  2186. UI_LoadMods
  2187. ===============
  2188. */
  2189. static void UI_LoadMods() {
  2190.     int        numdirs;
  2191.     char    dirlist[2048];
  2192.     char    *dirptr;
  2193.   char  *descptr;
  2194.     int        i;
  2195.     int        dirlen;
  2196.  
  2197.     uiInfo.modCount = 0;
  2198.     numdirs = trap_FS_GetFileList( "$modlist", "", dirlist, sizeof(dirlist) );
  2199.     dirptr  = dirlist;
  2200.     for( i = 0; i < numdirs; i++ ) {
  2201.         dirlen = strlen( dirptr ) + 1;
  2202.     descptr = dirptr + dirlen;
  2203.         uiInfo.modList[uiInfo.modCount].modName = String_Alloc(dirptr);
  2204.         uiInfo.modList[uiInfo.modCount].modDescr = String_Alloc(descptr);
  2205.     dirptr += dirlen + strlen(descptr) + 1;
  2206.         uiInfo.modCount++;
  2207.         if (uiInfo.modCount >= MAX_MODS) {
  2208.             break;
  2209.         }
  2210.     }
  2211.  
  2212. }
  2213.  
  2214. /*
  2215. ===============
  2216. UI_LoadMovies
  2217. ===============
  2218. */
  2219. static void UI_LoadMovies() {
  2220.     char    movielist[4096];
  2221.     char    *moviename;
  2222.     int        i, len;
  2223.  
  2224.     uiInfo.movieCount = trap_FS_GetFileList( "video", "roq", movielist, 4096 );
  2225.  
  2226.     if (uiInfo.movieCount) {
  2227.         if (uiInfo.movieCount > MAX_MOVIES) {
  2228.             uiInfo.movieCount = MAX_MOVIES;
  2229.         }
  2230.         moviename = movielist;
  2231.         for ( i = 0; i < uiInfo.movieCount; i++ ) {
  2232.             len = strlen( moviename );
  2233.             if (!Q_stricmp(moviename +  len - 4,".roq")) {
  2234.                 moviename[len-4] = '\0';
  2235.             }
  2236.             Q_strupr(moviename);
  2237.             uiInfo.movieList[i] = String_Alloc(moviename);
  2238.             moviename += len + 1;
  2239.         }
  2240.     }
  2241.  
  2242. }
  2243.  
  2244. /*
  2245. ===============
  2246. UI_LoadDemos
  2247. ===============
  2248. */
  2249. static void UI_LoadDemos() 
  2250. {
  2251.     char    demolist[4096];
  2252.     char demoExt[32];
  2253.     char    *demoname;
  2254.     int        i, len;
  2255.  
  2256.     Com_sprintf(demoExt, sizeof(demoExt), "dm_%d", (int)trap_Cvar_VariableValue("protocol"));
  2257.  
  2258.     uiInfo.demoCount = trap_FS_GetFileList( "demos", demoExt, demolist, 4096 );
  2259.  
  2260.     Com_sprintf(demoExt, sizeof(demoExt), ".dm_%d", (int)trap_Cvar_VariableValue("protocol"));
  2261.  
  2262.     if (uiInfo.demoCount) {
  2263.         if (uiInfo.demoCount > MAX_DEMOS) {
  2264.             uiInfo.demoCount = MAX_DEMOS;
  2265.         }
  2266.         demoname = demolist;
  2267.         for ( i = 0; i < uiInfo.demoCount; i++ ) {
  2268.             len = strlen( demoname );
  2269.             if (!Q_stricmp(demoname +  len - strlen(demoExt), demoExt)) {
  2270.                 demoname[len-strlen(demoExt)] = '\0';
  2271.             }
  2272.             Q_strupr(demoname);
  2273.             uiInfo.demoList[i] = String_Alloc(demoname);
  2274.             demoname += len + 1;
  2275.         }
  2276.     }
  2277.  
  2278. }
  2279.  
  2280.  
  2281. static qboolean UI_SetNextMap(int actual, int index) {
  2282.     int i;
  2283.     for (i = actual + 1; i < uiInfo.mapCount; i++) {
  2284.         if (uiInfo.mapList[i].active) {
  2285.             Menu_SetFeederSelection(NULL, FEEDER_MAPS, index + 1, "skirmish");
  2286.             return qtrue;
  2287.         }
  2288.     }
  2289.     return qfalse;
  2290. }
  2291.  
  2292. static void UI_Update ( const char *name ) 
  2293. {
  2294.     int    val = trap_Cvar_VariableValue(name);
  2295.  
  2296.      if (Q_stricmp(name, "ui_SetName") == 0) 
  2297.     {
  2298.         trap_Cvar_Set( "name", UI_Cvar_VariableString("ui_Name"));
  2299.      } 
  2300.     else if (Q_stricmp(name, "ui_setRate") == 0) 
  2301.     {
  2302.         float rate = trap_Cvar_VariableValue("rate");
  2303.         if (rate >= 5000) 
  2304.         {
  2305.             trap_Cvar_Set("cl_maxpackets", "30");
  2306.             trap_Cvar_Set("cl_packetdup", "1");
  2307.         } 
  2308.         else if (rate >= 4000) 
  2309.         {
  2310.             trap_Cvar_Set("cl_maxpackets", "15");
  2311.             trap_Cvar_Set("cl_packetdup", "2");        // favor less prediction errors when there's packet loss
  2312.         } 
  2313.         else 
  2314.         {
  2315.             trap_Cvar_Set("cl_maxpackets", "15");
  2316.             trap_Cvar_Set("cl_packetdup", "1");        // favor lower bandwidth
  2317.         }
  2318.      } 
  2319.     else if (Q_stricmp(name, "ui_GetName") == 0) 
  2320.     {
  2321.         trap_Cvar_Set( "ui_Name", UI_Cvar_VariableString("name"));
  2322.      } 
  2323.     else if (Q_stricmp(name, "r_colorbits") == 0) 
  2324.     {
  2325.         switch (val) 
  2326.         {
  2327.             case 0:
  2328.                 trap_Cvar_SetValue( "r_depthbits", 0 );
  2329.                 trap_Cvar_SetValue( "r_stencilbits", 0 );
  2330.             break;
  2331.             case 16:
  2332.                 trap_Cvar_SetValue( "r_depthbits", 16 );
  2333.                 trap_Cvar_SetValue( "r_stencilbits", 0 );
  2334.             break;
  2335.             case 32:
  2336.                 trap_Cvar_SetValue( "r_depthbits", 24 );
  2337.             break;
  2338.         }
  2339.     } 
  2340.     else if (Q_stricmp(name, "r_lodbias") == 0) 
  2341.     {
  2342.         switch (val) 
  2343.         {
  2344.             case 0:
  2345.                 trap_Cvar_SetValue( "r_subdivisions", 4 );
  2346.                 break;
  2347.             
  2348.             case 1:
  2349.                 trap_Cvar_SetValue( "r_subdivisions", 12 );
  2350.                 break;
  2351.             
  2352.             case 2:
  2353.                 trap_Cvar_SetValue( "r_subdivisions", 20 );
  2354.                 break;
  2355.         }
  2356.     } 
  2357.     else if (Q_stricmp(name, "ui_glCustom") == 0) 
  2358.     {
  2359.         switch (val) 
  2360.         {
  2361.             case 0:    // high quality
  2362.                 trap_Cvar_SetValue( "r_fullScreen", 1 );
  2363.                 trap_Cvar_SetValue( "r_subdivisions", 4 );
  2364.                 trap_Cvar_SetValue( "r_lodbias", 0 );
  2365.                 trap_Cvar_SetValue( "r_colorbits", 32 );
  2366.                 trap_Cvar_SetValue( "r_depthbits", 24 );
  2367.                 trap_Cvar_SetValue( "r_picmip", 1 );
  2368.                 trap_Cvar_SetValue( "r_mode", 4 );
  2369.                 trap_Cvar_SetValue( "r_texturebits", 32 );
  2370.                 trap_Cvar_SetValue( "r_fastSky", 0 );
  2371.                 trap_Cvar_SetValue( "r_inGameVideo", 1 );
  2372.                 trap_Cvar_SetValue( "cg_shadows", 1 );
  2373.                 trap_Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" );
  2374.                 break;
  2375.  
  2376.             case 1: // normal 
  2377.                 trap_Cvar_SetValue( "r_fullScreen", 1 );
  2378.                 trap_Cvar_SetValue( "r_subdivisions", 12 );
  2379.                 trap_Cvar_SetValue( "r_lodbias", 0 );
  2380.                 trap_Cvar_SetValue( "r_colorbits", 0 );
  2381.                 trap_Cvar_SetValue( "r_depthbits", 24 );
  2382.                 trap_Cvar_SetValue( "r_picmip", 2 );
  2383.                 trap_Cvar_SetValue( "r_mode", 3 );
  2384.                 trap_Cvar_SetValue( "r_texturebits", 0 );
  2385.                 trap_Cvar_SetValue( "r_fastSky", 0 );
  2386.                 trap_Cvar_SetValue( "r_inGameVideo", 1 );
  2387.                 trap_Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" );
  2388.                 trap_Cvar_SetValue( "cg_shadows", 0 );
  2389.                 break;
  2390.  
  2391.             case 2: // fast
  2392.                 trap_Cvar_SetValue( "r_fullScreen", 1 );
  2393.                 trap_Cvar_SetValue( "r_subdivisions", 8 );
  2394.                 trap_Cvar_SetValue( "r_lodbias", 1 );
  2395.                 trap_Cvar_SetValue( "r_colorbits", 0 );
  2396.                 trap_Cvar_SetValue( "r_depthbits", 0 );
  2397.                 trap_Cvar_SetValue( "r_picmip", 3 );
  2398.                 trap_Cvar_SetValue( "r_mode", 3 );
  2399.                 trap_Cvar_SetValue( "r_texturebits", 0 );
  2400.                 trap_Cvar_SetValue( "cg_shadows", 0 );
  2401.                 trap_Cvar_SetValue( "r_fastSky", 1 );
  2402.                 trap_Cvar_SetValue( "r_inGameVideo", 0 );
  2403.                 trap_Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_NEAREST" );
  2404.                 break;
  2405.  
  2406.             case 3: // fastest
  2407.                 trap_Cvar_SetValue( "r_fullScreen", 1 );
  2408.                 trap_Cvar_SetValue( "r_subdivisions", 20 );
  2409.                 trap_Cvar_SetValue( "r_lodbias", 2 );
  2410.                 trap_Cvar_SetValue( "r_colorbits", 16 );
  2411.                 trap_Cvar_SetValue( "r_depthbits", 16 );
  2412.                 trap_Cvar_SetValue( "r_mode", 3 );
  2413.                 trap_Cvar_SetValue( "r_picmip", 3 );
  2414.                 trap_Cvar_SetValue( "r_texturebits", 16 );
  2415.                 trap_Cvar_SetValue( "cg_shadows", 0 );
  2416.                 trap_Cvar_SetValue( "r_fastSky", 1 );
  2417.                 trap_Cvar_SetValue( "r_inGameVideo", 0 );
  2418.                 trap_Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_NEAREST" );
  2419.                 break;
  2420.         }
  2421.     } 
  2422.     else if (Q_stricmp(name, "ui_mousePitch") == 0) 
  2423.     {
  2424.         if (val == 0) 
  2425.         {
  2426.             trap_Cvar_SetValue( "m_pitch", 0.022f );
  2427.         } 
  2428.         else 
  2429.         {
  2430.             trap_Cvar_SetValue( "m_pitch", -0.022f );
  2431.         }
  2432.     }
  2433. }
  2434.  
  2435. /*
  2436. ===============
  2437. UI_VerifyNetwork
  2438.  
  2439. Verifies that there is a network connection and if not dumps a com_error
  2440. ===============
  2441. */
  2442. qboolean UI_VerifyNetwork ( void )
  2443. {
  2444.     if ( ui_noNetCheck.integer )
  2445.     {
  2446.         return qtrue;
  2447.     }
  2448.  
  2449.     if ( !trap_NET_Available ( ) )
  2450.     {
  2451.         if ( !(int)trap_Cvar_VariableValue ( "com_ignoreverifynetwork" ) )
  2452.         {
  2453.             Menus_ActivateByName("verifynetwork_popmenu");
  2454.             return qfalse;
  2455.         }
  2456.     }
  2457.  
  2458.     return qtrue;
  2459. }
  2460.  
  2461. /*
  2462. ===============
  2463. UI_RunMenuScript
  2464.  
  2465. Runs scripts from the menu
  2466. ===============
  2467. */
  2468. static void UI_RunMenuScript(const char **args) 
  2469. {
  2470.     const char *name, *name2;
  2471.     char buff[1024];
  2472.  
  2473.     if (String_Parse(args, &name)) 
  2474.     {        
  2475.         if ( Q_stricmp ( name, "LoadOutfittings" ) == 0 )
  2476.         {
  2477.             BG_SetAvailableOutfitting ( UI_Cvar_VariableString ( "ui_info_availableweapons" ) );
  2478.             
  2479.             BG_ParseOutfittingTemplates ( qfalse );
  2480.         }
  2481.         else if ( Q_stricmp ( name, "DecompressOutfitting" ) == 0 )
  2482.         {
  2483.             int                index;
  2484.             goutfitting_t    outfitting;
  2485.  
  2486.             BG_DecompressOutfitting ( UI_Cvar_VariableString ( "outfitting" ), &outfitting );
  2487.  
  2488.             index = BG_FindOutfitting ( &outfitting );
  2489.             if ( index < 0 )
  2490.             {
  2491.                 memcpy ( &bg_outfittings[0].items[0], &outfitting.items[0], sizeof(outfitting.items) );
  2492.                 Menu_SetFeederSelection(NULL, FEEDER_OUTFITTING_TEMPLATES, 0, "main");
  2493.             }
  2494.             else
  2495.             {
  2496.                 Menu_SetFeederSelection(NULL, FEEDER_OUTFITTING_TEMPLATES, index, "main");
  2497.             }
  2498.         }
  2499.         else if ( Q_stricmp ( name, "CompressOutfitting" ) == 0 )
  2500.         {
  2501.             char compressed[OUTFITTING_GROUP_MAX + 1];
  2502.             BG_CompressOutfitting ( &bg_outfittings[uiInfo.outfittingItemGroup], compressed, OUTFITTING_GROUP_MAX );
  2503.             trap_Cvar_Set ( "outfitting", compressed );
  2504.         }
  2505.         // Verify that the user is connected and if not through a com_error
  2506.         else if ( Q_stricmp ( name, "VerifyNet" ) == 0 )
  2507.         {
  2508.             UI_VerifyNetwork ( );
  2509.         }
  2510.         else if ( Q_stricmp ( name, "autoTeamJoin" ) == 0 )
  2511.         {
  2512.             qboolean joinRed = qfalse;
  2513.  
  2514.             if ( !String_Parse(args, &name) || !name )
  2515.             {
  2516.                 return;
  2517.             }
  2518.  
  2519.             if ( !String_Parse(args, &name2) || !name2 )
  2520.             {
  2521.                 return;
  2522.             }
  2523.  
  2524.             // If the teams have the same number of players then join the 
  2525.             // team that has less points
  2526.             if ( ui_info_bluecount.integer == ui_info_redcount.integer )
  2527.             {
  2528.                 // If the blue team has more points then join red
  2529.                 if ( ui_info_bluescore.integer > ui_info_redscore.integer )
  2530.                 {
  2531.                     joinRed = qtrue;
  2532.                 }
  2533.             }
  2534.             // If the blue team has more players then join red
  2535.             else if ( ui_info_bluecount.integer > ui_info_redcount.integer )
  2536.             {
  2537.                 joinRed = qtrue;
  2538.             }
  2539.                     
  2540.             if ( joinRed )
  2541.             {
  2542.                 Menus_OpenByName ( name );
  2543.             }
  2544.             else 
  2545.             {
  2546.                 Menus_OpenByName ( name2 );
  2547.             }
  2548.         }
  2549.         else if ( Q_stricmp ( name, "JoinTeam" ) == 0 )
  2550.         {
  2551.             int        index;
  2552.             team_t    team;
  2553.  
  2554.             if ( !String_Parse(args, &name) || !name )
  2555.             {
  2556.                 return;
  2557.             }
  2558.  
  2559.             if ( !Int_Parse ( args, &index ) )
  2560.             {
  2561.                 return;
  2562.             }
  2563.  
  2564.             if ( Q_stricmp ( name, "red" ) == 0 )
  2565.             {
  2566.                 team = TEAM_RED;
  2567.             }
  2568.             else if ( Q_stricmp ( name, "blue" ) == 0 )
  2569.             {
  2570.                 team = TEAM_BLUE;
  2571.             }
  2572.             else
  2573.             {    
  2574.                 return;
  2575.             }
  2576.  
  2577.             if ( index < 0 || index > 4 )
  2578.             {
  2579.                 index = 0;
  2580.             }
  2581.  
  2582.             if ( !uiInfo.identityTeams[team][index] )
  2583.             {
  2584.                 return;
  2585.             }
  2586.  
  2587.             trap_Cmd_ExecuteText( EXEC_APPEND, va("cmd team %s %s\n", name, uiInfo.identityTeams[team][index]->mName ));
  2588.         }
  2589.         else if ( Q_stricmp ( name, "UpdateModel" ) == 0 )
  2590.         {
  2591.             updateModel = qtrue;
  2592.         }
  2593.         else if ( Q_stricmp ( name, "UpdateParental" ) == 0 )
  2594.         {
  2595.             char password[MAX_QPATH];
  2596.             trap_Parental_GetPassword ( password, MAX_QPATH );
  2597.  
  2598.             // As long as the password is correct, let them by
  2599.             if ( Q_stricmp ( password, uiInfo.parentalPassword ) == 0 )
  2600.             {
  2601.                 trap_Parental_Update ( );
  2602.             }
  2603.         }
  2604.         else if ( Q_stricmp ( name, "OpenParentalPasswordMenu" ) == 0 )
  2605.         {
  2606.                 trap_Cvar_Set ( "ui_lock_password2", "" );                
  2607.         }
  2608.         else if ( Q_stricmp ( name, "UpdateParentalPassword" ) == 0 )
  2609.         {
  2610.             char password[MAX_QPATH],password2[MAX_QPATH];
  2611.  
  2612.             trap_Cvar_VariableStringBuffer ( "ui_lock_password", password, MAX_QPATH );
  2613.             trap_Cvar_VariableStringBuffer ( "ui_lock_password2", password2, MAX_QPATH );
  2614.  
  2615.             if ( !Q_stricmp ( password, password2  ) )
  2616.             {
  2617.                 trap_Cvar_VariableStringBuffer ( "ui_lock_password", uiInfo.parentalPassword , MAX_QPATH );
  2618.                 trap_Parental_SetPassword ( uiInfo.parentalPassword );    
  2619.  
  2620.                 trap_Cvar_Set ( "ui_lock_password", "" );
  2621.  
  2622.                 Menus_CloseByName("violence_setpassword_popmenu");
  2623.             }
  2624.             else
  2625.             {
  2626.                 trap_Cvar_Set ( "setpassword_error", "Password and Re-Enter Password must match." );
  2627.             }
  2628.         }
  2629.         else if (Q_stricmp(name,"violence_options") == 0 ) 
  2630.         {
  2631.             char password[MAX_QPATH];
  2632.             trap_Parental_GetPassword ( password, MAX_QPATH );
  2633.             trap_Cvar_VariableStringBuffer ( "ui_lock_password", uiInfo.parentalPassword, MAX_QPATH );
  2634.  
  2635.             if ( !Q_stricmp ( password, uiInfo.parentalPassword  ) )
  2636.             {
  2637.                 Menus_CloseByName ( "violence_menu" );
  2638.                 Menus_OpenByName ( "violence_options_menu" );
  2639.                 trap_Cvar_Set ( "parental_password_error", " " );
  2640.             }
  2641.             else
  2642.             {
  2643.                 trap_Cvar_Set ( "parental_password_error", "Incorrect password." );
  2644.             }
  2645.             trap_Cvar_Set ( "ui_lock_password", "" );
  2646.         } 
  2647.         else if (Q_stricmp(name, "SetConnectPassword") == 0)
  2648.         {
  2649.             char password[MAX_QPATH];
  2650.             uiInfo.connectPasswordRequest = qfalse;
  2651.             trap_Cvar_VariableStringBuffer ( "ui_connect_password", password, MAX_QPATH );
  2652.             trap_Cvar_Set ( "password", password );
  2653.             trap_Cvar_Set ( "ui_connect_password", "" );
  2654.         }
  2655.         else if (Q_stricmp(name, "StartServer") == 0) 
  2656.         {
  2657. #ifdef _SOF2_BOTS
  2658.             int        clients;
  2659.             int        oldclients;
  2660.             float    skill;
  2661. #endif
  2662.  
  2663.             trap_Cvar_Set("cg_thirdPerson", "0");
  2664.             trap_Cvar_Set("cg_cameraOrbit", "0");
  2665.             trap_Cvar_SetValue( "dedicated", Com_Clamp( 0, 2, ui_dedicated.integer ) );
  2666.             trap_Cvar_Set ( "g_gametype", bg_gametypeData[ui_netGameType.integer].name );
  2667.  
  2668.             // Must be connected
  2669.             if ( ui_dedicated.integer > 0 )
  2670.             {
  2671.                 if ( !UI_VerifyNetwork ( ) )
  2672.                 {
  2673.                     return;
  2674.                 }
  2675.             }
  2676.  
  2677.             // Handle randomly generated maps specially
  2678.             if ( !Q_stricmp ( uiInfo.mapList[ui_currentNetMap.integer].mapLoadName, "*random" ) )
  2679.             {
  2680.                 char    rmgConfig[MAX_QPATH];
  2681.                 char    rmgSize[MAX_QPATH];
  2682.                 char    rmgTime[MAX_QPATH];
  2683.                 char    rmgSeed[MAX_QPATH];
  2684.  
  2685.  
  2686.                 trap_Cvar_VariableStringBuffer ( "ui_rmg_size", rmgSize, MAX_QPATH );
  2687.                 trap_Cvar_VariableStringBuffer ( "ui_rmg_config", rmgConfig, MAX_QPATH );
  2688.                 trap_Cvar_VariableStringBuffer ( "ui_rmg_time", rmgTime, MAX_QPATH );
  2689.                 trap_Cvar_VariableStringBuffer ( "ui_rmg_seed", rmgSeed, MAX_QPATH );
  2690.  
  2691.                 trap_Cmd_ExecuteText ( EXEC_APPEND, va( "wait ; wait ; rmgmap 1 \"%s\" 2 \"%s\" 3 \"%s\" 4 \"%s\" 0\n", 
  2692.                     rmgSize, rmgConfig, rmgTime, rmgSeed  ) );
  2693.             }
  2694.             else
  2695.             {
  2696.                 trap_Cmd_ExecuteText ( EXEC_APPEND, va( "wait ; wait ; map %s\n", uiInfo.mapList[ui_currentNetMap.integer].mapLoadName ) );
  2697.             }
  2698. #ifdef _SOF2_BOTS
  2699.  
  2700.             skill = trap_Cvar_VariableValue( "g_botSkill" );    
  2701.     
  2702.             // set max clients based on spots
  2703.             oldclients = trap_Cvar_VariableValue( "sv_maxClients" );
  2704.             clients    = 0;
  2705.  
  2706.             if (clients == 0) 
  2707.             {
  2708.                 clients = 8;
  2709.             }
  2710.             
  2711.             if (oldclients > clients) 
  2712.             {
  2713.                 clients = oldclients;
  2714.             }
  2715.  
  2716.             trap_Cvar_Set("sv_maxClients", va("%d",clients));
  2717. #endif
  2718.         } 
  2719.         else if (Q_stricmp(name, "resetDefaults") == 0) 
  2720.         {
  2721.             trap_Cmd_ExecuteText( EXEC_APPEND, "exec sof2mp_default.cfg\n");
  2722.             trap_Cmd_ExecuteText( EXEC_APPEND, "cvar_restart\n");
  2723.             Controls_SetDefaults();
  2724.             trap_Cmd_ExecuteText( EXEC_APPEND, "vid_restart\n" );
  2725.         } 
  2726.         else if (Q_stricmp(name, "getCDKey") == 0) {
  2727.             char out[17];
  2728.             trap_GetCDKey(buff, 17);
  2729.             trap_Cvar_Set("cdkey1", "");
  2730.             trap_Cvar_Set("cdkey2", "");
  2731.             trap_Cvar_Set("cdkey3", "");
  2732.             trap_Cvar_Set("cdkey4", "");
  2733.             trap_Cvar_Set("cdkeychecksum", "");
  2734.             trap_Cvar_Set("cdkey_error", "");
  2735.             
  2736.             if (strlen(buff) == CDKEY_LEN) 
  2737.             {
  2738.                 Q_strncpyz(out, buff, 5);
  2739.                 trap_Cvar_Set("cdkey1", out);
  2740.                 Q_strncpyz(out, buff + 4, 5);
  2741.                 trap_Cvar_Set("cdkey2", out);
  2742.                 Q_strncpyz(out, buff + 8, 5);
  2743.                 trap_Cvar_Set("cdkey3", out);
  2744.                 Q_strncpyz(out, buff + 12, 5);
  2745.                 trap_Cvar_Set("cdkey4", out);
  2746.                 Q_strncpyz(out, buff + 16, 2);
  2747.                 trap_Cvar_Set("cdkeychecksum", out);
  2748.             }
  2749.  
  2750.         } else if (Q_stricmp(name, "verifyCDKey") == 0) {
  2751.             buff[0] = '\0';
  2752.             Q_strcat(buff, 1024, UI_Cvar_VariableString("cdkey1")); 
  2753.             Q_strcat(buff, 1024, UI_Cvar_VariableString("cdkey2")); 
  2754.             Q_strcat(buff, 1024, UI_Cvar_VariableString("cdkey3")); 
  2755.             Q_strcat(buff, 1024, UI_Cvar_VariableString("cdkey4")); 
  2756.             Q_strcat(buff, 1024, UI_Cvar_VariableString("cdkeychecksum")); 
  2757.             trap_Cvar_Set("cdkey", buff);
  2758.  
  2759.             if (trap_VerifyCDKey(buff)) 
  2760.             {
  2761.                 trap_Cvar_Set("cdkey_error", "Valid CD Key.");
  2762.                 trap_SetCDKey(buff);
  2763.                 Menus_CloseByName ( "cdkey_popmenu" );
  2764.             } 
  2765.             else 
  2766.             {
  2767.                 trap_Cvar_Set("cdkey_error", "Invalid CD Key.");
  2768.             }            
  2769.         } 
  2770.         else if (Q_stricmp(name, "loadArenas") == 0) 
  2771.         {
  2772.             int actual;
  2773.  
  2774.             UI_LoadArenas();
  2775.             UI_MapCountByGameType();
  2776.             Menu_SetFeederSelection(NULL, FEEDER_ALLMAPS, 0, "createserver_menu");
  2777.  
  2778.             trap_Cvar_Set("ui_mapIndex", "0");
  2779.             ui_mapIndex.integer = 0;
  2780.             UI_SelectedMap ( 0, &actual );
  2781.             ui_currentNetMap.integer = actual;
  2782.             trap_Cvar_Set("ui_currentNetMap", va("%d",actual));
  2783.             trap_Cvar_Set("ui_currentNetMapName", uiInfo.mapList[actual].mapLoadName );
  2784.         } 
  2785.         else if (Q_stricmp(name, "loadVoteArenas") == 0) 
  2786.         {
  2787.             int actual;
  2788.  
  2789.             UI_LoadArenas();
  2790.             UI_MapCountForVote();
  2791.             Menu_SetFeederSelection(NULL, FEEDER_VOTEMAPS, 0, "ingame_callvote");
  2792.  
  2793.             trap_Cvar_Set("ui_mapIndex", "0");
  2794.             ui_mapIndex.integer = 0;
  2795.             UI_SelectedMap ( 0, &actual );
  2796.             ui_currentNetMap.integer = actual;
  2797.             trap_Cvar_Set("ui_currentNetMap", va("%d",actual));
  2798.             trap_Cvar_Set("ui_currentNetMapName", uiInfo.mapList[actual].mapLoadName );
  2799.         } 
  2800.         else if (Q_stricmp(name, "saveControls") == 0) {
  2801.             Controls_SetConfig(qtrue);
  2802.         } else if (Q_stricmp(name, "loadControls") == 0) {
  2803.             Controls_GetConfig();
  2804.         } else if (Q_stricmp(name, "clearError") == 0) {
  2805.             trap_Cvar_Set("com_errorMessage", "");
  2806.         } 
  2807.         else if (Q_stricmp(name, "loadGameInfo") == 0) 
  2808.         {
  2809.             BG_BuildGametypeList ( );                
  2810.         } else if (Q_stricmp(name, "RefreshServers") == 0) {
  2811.             UI_StartServerRefresh(qtrue);
  2812.             UI_BuildServerDisplayList(qtrue);
  2813.         } else if (Q_stricmp(name, "RefreshFilter") == 0) {
  2814.             UI_StartServerRefresh(qfalse);
  2815.             UI_BuildServerDisplayList(qtrue);
  2816.         } else if (Q_stricmp(name, "RunSPDemo") == 0) {
  2817.             if (uiInfo.demoAvailable) {
  2818.               trap_Cmd_ExecuteText( EXEC_APPEND, va("demo %s_%s\n", uiInfo.mapList[ui_currentMap.integer].mapLoadName, bg_gametypeData[ui_gameType.integer].name));
  2819.             }
  2820.         } else if (Q_stricmp(name, "LoadDemos") == 0) {
  2821.             UI_LoadDemos();
  2822.         } else if (Q_stricmp(name, "LoadMovies") == 0) {
  2823.             UI_LoadMovies();
  2824.         } else if (Q_stricmp(name, "LoadMods") == 0) {
  2825.             UI_LoadMods();
  2826.         } else if (Q_stricmp(name, "playMovie") == 0) {
  2827.             if (uiInfo.previewMovie >= 0) {
  2828.               trap_CIN_StopCinematic(uiInfo.previewMovie);
  2829.             }
  2830.             trap_Cmd_ExecuteText( EXEC_APPEND, va("cinematic %s.roq 2\n", uiInfo.movieList[uiInfo.movieIndex]));
  2831.         } else if (Q_stricmp(name, "RunMod") == 0) {
  2832.             trap_Cvar_Set( "fs_game", uiInfo.modList[uiInfo.modIndex].modName);
  2833.             trap_Cmd_ExecuteText( EXEC_APPEND, "vid_restart;" );
  2834.         } else if (Q_stricmp(name, "RunDemo") == 0) {
  2835.             trap_Cmd_ExecuteText( EXEC_APPEND, va("demo \"%s\"\n", uiInfo.demoList[uiInfo.demoIndex]));
  2836.         } else if (Q_stricmp(name, "Quake3") == 0) {
  2837.             trap_Cvar_Set( "fs_game", "");
  2838.             trap_Cmd_ExecuteText( EXEC_APPEND, "vid_restart;" );
  2839.         } else if (Q_stricmp(name, "closeJoin") == 0) {
  2840.             if (uiInfo.serverStatus.refreshActive) {
  2841.                 UI_StopServerRefresh();
  2842.                 uiInfo.serverStatus.nextDisplayRefresh = 0;
  2843.                 uiInfo.nextServerStatusRefresh = 0;
  2844.                 uiInfo.nextFindPlayerRefresh = 0;
  2845.                 UI_BuildServerDisplayList(qtrue);
  2846.             } else {
  2847.                 Menus_CloseByName("joinserver");
  2848.                 Menus_OpenByName("main");
  2849.             }
  2850.         } else if (Q_stricmp(name, "StopRefresh") == 0) {
  2851.             UI_StopServerRefresh();
  2852.             uiInfo.serverStatus.nextDisplayRefresh = 0;
  2853.             uiInfo.nextServerStatusRefresh = 0;
  2854.             uiInfo.nextFindPlayerRefresh = 0;
  2855.         } else if (Q_stricmp(name, "UpdateFilter") == 0) {
  2856.             if (ui_netSource.integer == AS_LOCAL) {
  2857.                 UI_StartServerRefresh(qtrue);
  2858.             }
  2859.             UI_BuildServerDisplayList(qtrue);
  2860.             UI_FeederSelection(FEEDER_SERVERS, 0);
  2861.         } else if (Q_stricmp(name, "ServerStatus") == 0) {
  2862.             trap_LAN_GetServerAddressString(ui_netSource.integer, uiInfo.serverStatus.displayServers[uiInfo.serverStatus.currentServer], uiInfo.serverStatusAddress, sizeof(uiInfo.serverStatusAddress));
  2863.             UI_BuildServerStatus(qtrue);
  2864.         } else if (Q_stricmp(name, "FoundPlayerServerStatus") == 0) {
  2865.             Q_strncpyz(uiInfo.serverStatusAddress, uiInfo.foundPlayerServerAddresses[uiInfo.currentFoundPlayerServer], sizeof(uiInfo.serverStatusAddress));
  2866.             UI_BuildServerStatus(qtrue);
  2867.             Menu_SetFeederSelection(NULL, FEEDER_FINDPLAYER, 0, NULL);
  2868.         } else if (Q_stricmp(name, "FindPlayer") == 0) {
  2869.             UI_BuildFindPlayerList(qtrue);
  2870.             // clear the displayed server status info
  2871.             uiInfo.serverStatusInfo.numLines = 0;
  2872.             Menu_SetFeederSelection(NULL, FEEDER_FINDPLAYER, 0, NULL);
  2873.         } else if (Q_stricmp(name, "JoinServer") == 0) {
  2874.             trap_Cvar_Set("cg_thirdPerson", "0");
  2875.             trap_Cvar_Set("cg_cameraOrbit", "0");
  2876.             if (uiInfo.serverStatus.currentServer >= 0 && uiInfo.serverStatus.currentServer < uiInfo.serverStatus.numDisplayServers) {
  2877.                 trap_LAN_GetServerAddressString(ui_netSource.integer, uiInfo.serverStatus.displayServers[uiInfo.serverStatus.currentServer], buff, 1024);
  2878.                 trap_Cmd_ExecuteText( EXEC_APPEND, va( "connect %s\n", buff ) );
  2879.             }
  2880.         } else if (Q_stricmp(name, "FoundPlayerJoinServer") == 0) {
  2881.             if (uiInfo.currentFoundPlayerServer >= 0 && uiInfo.currentFoundPlayerServer < uiInfo.numFoundPlayerServers) {
  2882.                 trap_Cmd_ExecuteText( EXEC_APPEND, va( "connect %s\n", uiInfo.foundPlayerServerAddresses[uiInfo.currentFoundPlayerServer] ) );
  2883.             }
  2884.         } 
  2885.         else if (Q_stricmp(name, "Quit") == 0) {
  2886.             trap_Cmd_ExecuteText( EXEC_NOW, "quit");
  2887.         } else if (Q_stricmp(name, "Controls") == 0) {
  2888.           trap_Cvar_Set( "cl_paused", "1" );
  2889.             trap_Key_SetCatcher( KEYCATCH_UI );
  2890.             Menus_CloseAll();
  2891.             Menus_ActivateByName("setup_menu2");
  2892.         } else if (Q_stricmp(name, "Leave") == 0) 
  2893.         {
  2894.             uiInfo.connectPasswordRequest = qfalse;
  2895.             trap_Cmd_ExecuteText( EXEC_APPEND, "disconnect\n" );
  2896.             trap_Key_SetCatcher( KEYCATCH_UI );
  2897.             Menus_CloseAll();
  2898.             Menus_ActivateByName("main");
  2899.         } else if (Q_stricmp(name, "ServerSort") == 0) {
  2900.             int sortColumn;
  2901.             if (Int_Parse(args, &sortColumn)) {
  2902.                 // if same column we're already sorting on then flip the direction
  2903.                 if (sortColumn == uiInfo.serverStatus.sortKey) {
  2904.                     uiInfo.serverStatus.sortDir = !uiInfo.serverStatus.sortDir;
  2905.                 }
  2906.                 // make sure we sort again
  2907.                 UI_ServersSort(sortColumn, qtrue);
  2908.             }
  2909.         } else if (Q_stricmp(name, "closeingame") == 0) {
  2910.             trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );
  2911.             trap_Key_ClearStates();
  2912.             trap_Cvar_Set( "cl_paused", "0" );
  2913.             Menus_CloseAll();
  2914.         } 
  2915.         else if (Q_stricmp(name, "voteMap") == 0) 
  2916.         {
  2917.             if (ui_currentNetMap.integer >=0 && ui_currentNetMap.integer < uiInfo.mapCount) 
  2918.             {
  2919.                 trap_Cmd_ExecuteText( EXEC_APPEND, va("callvote map %s\n",uiInfo.mapList[ui_currentNetMap.integer].mapLoadName) );
  2920.             }
  2921.         } 
  2922.         else if (Q_stricmp(name, "voteKick") == 0) 
  2923.         {
  2924.             if (uiInfo.playerIndex >= 0 && uiInfo.playerIndex < uiInfo.playerCount) 
  2925.             {
  2926.                 char clientnum[3];
  2927.                 
  2928.                 // The client number is hidden in front of the string
  2929.                 strncpy ( clientnum, uiInfo.playerNames[uiInfo.playerIndex], 2 );
  2930.                 clientnum[2] = 0;
  2931.  
  2932.                 trap_Cmd_ExecuteText( EXEC_APPEND, va("callvote clientkick \"%s\"\n",clientnum) );
  2933.             }
  2934.         } 
  2935.         else if (Q_stricmp(name, "voteGame") == 0) 
  2936.         {
  2937.             if (ui_netGameType.integer >= 0 && ui_netGameType.integer < bg_gametypeCount ) 
  2938.             {
  2939.                 trap_Cmd_ExecuteText( EXEC_APPEND, va("callvote g_gametype %s\n",bg_gametypeData[ui_netGameType.integer].name) );
  2940.             }
  2941.         }
  2942.         else if ( Q_stricmp ( name, "voteRMG" ) == 0 )
  2943.         {
  2944.             char    rmgConfig[MAX_QPATH];
  2945.             char    rmgSize[MAX_QPATH];
  2946.             char    rmgTime[MAX_QPATH];
  2947.             char    rmgSeed[MAX_QPATH];
  2948.  
  2949.             trap_Cvar_VariableStringBuffer ( "ui_rmg_size", rmgSize, MAX_QPATH );
  2950.             trap_Cvar_VariableStringBuffer ( "ui_rmg_config", rmgConfig, MAX_QPATH );
  2951.             trap_Cvar_VariableStringBuffer ( "ui_rmg_time", rmgTime, MAX_QPATH );
  2952.             trap_Cvar_VariableStringBuffer ( "ui_rmg_seed", rmgSeed, MAX_QPATH );
  2953.  
  2954.             trap_Cmd_ExecuteText ( EXEC_APPEND, va( "callvote rmgmap \"%s\" \"%s\" \"%s\" \"%s\"\n", 
  2955.                                    rmgSize, rmgConfig, rmgTime, rmgSeed  ) );            
  2956.         } 
  2957.         else if (Q_stricmp(name, "loadNewVersionFromBrowser") == 0) 
  2958.         {
  2959.             trap_Version_Download(VD_BROWSER_DOWNLOAD);
  2960.         } 
  2961.         else if (Q_stricmp(name, "ignoreCurrentVersion") == 0) 
  2962.         {
  2963.             Menus_CloseByName("invalid_version_ignore_menu");
  2964.             Menus_CloseByName("invalid_version_menu");
  2965.             trap_Version_Download(VD_IGNORE);
  2966.         }
  2967.         else if (Q_stricmp(name, "loadNewVersion") == 0) 
  2968.         {
  2969.             Menus_ActivateByName("patch_download");
  2970.             trap_Version_Download(uiInfo.versionIndex);
  2971.         } 
  2972.         else if (Q_stricmp(name, "cancelDownload") == 0) 
  2973.         {
  2974.             trap_Version_Download(VD_CANCEL);
  2975.         }
  2976.         else if (Q_stricmp(name, "addBot") == 0) 
  2977.         {
  2978.             trap_Cmd_ExecuteText( EXEC_APPEND, va("addbot %s %i %s\n", UI_GetBotNameByNumber(uiInfo.botIndex), uiInfo.skillIndex+1, ui_botteam.string ) );
  2979.         } 
  2980.         else if (Q_stricmp(name, "addFavorite") == 0) 
  2981.         {
  2982.             if (ui_netSource.integer != AS_FAVORITES) {
  2983.                 char name[MAX_NAME_LENGTH];
  2984.                 char addr[MAX_NAME_LENGTH];
  2985.                 int res;
  2986.  
  2987.                 trap_LAN_GetServerInfo(ui_netSource.integer, uiInfo.serverStatus.displayServers[uiInfo.serverStatus.currentServer], buff, MAX_STRING_CHARS);
  2988.                 name[0] = addr[0] = '\0';
  2989.                 Q_strncpyz(name,     Info_ValueForKey(buff, "hostname"), MAX_NAME_LENGTH);
  2990.                 Q_strncpyz(addr,     Info_ValueForKey(buff, "addr"), MAX_NAME_LENGTH);
  2991.                 if (strlen(name) > 0 && strlen(addr) > 0) {
  2992.                     res = trap_LAN_AddServer(AS_FAVORITES, name, addr);
  2993.                     if (res == 0) {
  2994.                         // server already in the list
  2995.                         Com_Printf("Favorite already in list\n");
  2996.                     }
  2997.                     else if (res == -1) {
  2998.                         // list full
  2999.                         Com_Printf("Favorite list full\n");
  3000.                     }
  3001.                     else {
  3002.                         // successfully added
  3003.                         Com_Printf("Added favorite server %s\n", addr);
  3004.                     }
  3005.                 }
  3006.             }
  3007.         } 
  3008.         else if (Q_stricmp(name, "deleteFavorite") == 0) 
  3009.         {
  3010.             if (ui_netSource.integer == AS_FAVORITES) 
  3011.             {
  3012.                 char addr[MAX_NAME_LENGTH];
  3013.  
  3014.                 trap_LAN_GetServerInfo(ui_netSource.integer, uiInfo.serverStatus.displayServers[uiInfo.serverStatus.currentServer], buff, MAX_STRING_CHARS);
  3015.                 addr[0] = '\0';
  3016.                 Q_strncpyz(addr,     Info_ValueForKey(buff, "addr"), MAX_NAME_LENGTH);
  3017.                 if (strlen(addr) > 0) {
  3018.                     trap_LAN_RemoveServer(AS_FAVORITES, addr);
  3019.                 }
  3020.  
  3021.                 UI_BuildServerDisplayList(qtrue);
  3022.             }
  3023.         } 
  3024.         else if (Q_stricmp(name, "CancelCreateFavorite") == 0) 
  3025.         {
  3026.             trap_Cvar_Set( "fave_ip_error", " " );                
  3027.             trap_Cvar_Set( "ui_favoriteAddress", " " );                
  3028.         }
  3029.         else if (Q_stricmp(name, "createFavorite") == 0) 
  3030.         {
  3031.             char    name[MAX_NAME_LENGTH];
  3032.             char    addr[MAX_NAME_LENGTH];
  3033.             int        res;
  3034.  
  3035.             name[0] = addr[0] = '\0';
  3036.             Q_strncpyz(name,     UI_Cvar_VariableString("ui_favoriteAddress"), MAX_NAME_LENGTH);
  3037.             Q_strncpyz(addr,     UI_Cvar_VariableString("ui_favoriteAddress"), MAX_NAME_LENGTH);
  3038.  
  3039.             if ( strlen(name) > 0 && strlen(addr) > 0) 
  3040.             {
  3041.                 res = trap_LAN_AddServer(AS_FAVORITES, name, addr);
  3042.                 if (res == 0) 
  3043.                 {
  3044.                     // server already in the list
  3045.                     Com_Printf("Favorite already in list\n");
  3046.                 }
  3047.                 else if (res == -1) 
  3048.                 {
  3049.                     // list full
  3050.                     Com_Printf("Favorite list full\n");
  3051.                 }
  3052.                 else if (res == -2) 
  3053.                 {
  3054.                     trap_Cvar_Set( "fave_ip_error", "Invalid address." );                
  3055.                 }
  3056.                 else 
  3057.                 {
  3058.                     // successfully added
  3059.                     Com_Printf("Added favorite server %s\n", addr);
  3060.                     trap_Cvar_Set( "fave_ip_error", " " );                
  3061.                     trap_Cvar_Set( "ui_favoriteAddress", " " );                
  3062.                     Menus_CloseByName("createfavorite_popmenu");
  3063.                 }
  3064.  
  3065.                 UI_BuildServerDisplayList(qtrue);
  3066.             }
  3067.         } 
  3068.         else if (Q_stricmp(name, "display_settings_store") == 0)
  3069.         {    
  3070.             trap_Cvar_SetValue( "ui_glCustom_store", trap_Cvar_VariableValue("ui_glCustom") );
  3071.             trap_Cvar_SetValue( "r_fullscreen_store",trap_Cvar_VariableValue("r_fullscreen") );
  3072.             trap_Cvar_SetValue( "r_allowExtensions_store", trap_Cvar_VariableValue("r_allowExtensions") );
  3073.             trap_Cvar_SetValue( "r_mode_store", trap_Cvar_VariableValue("r_mode") );
  3074.             trap_Cvar_SetValue( "r_colorbits_store",trap_Cvar_VariableValue("r_colorbits") );
  3075.             trap_Cvar_SetValue( "r_lodbias_store", trap_Cvar_VariableValue("r_lodbias") );
  3076.             trap_Cvar_SetValue( "r_picmip_store", trap_Cvar_VariableValue("r_picmip") );
  3077.             trap_Cvar_SetValue( "r_texturebits_store", trap_Cvar_VariableValue("r_texturebits") );
  3078.             trap_Cvar_SetValue( "r_texturemode_store", trap_Cvar_VariableValue("r_texturemode") );
  3079.             trap_Cvar_SetValue( "r_ext_compressed_textures_store", trap_Cvar_VariableValue("r_ext_compressed_textures") ); 
  3080.         }
  3081.         else if (Q_stricmp(name, "display_settings_recall") == 0)
  3082.         {
  3083.             trap_Cvar_SetValue( "ui_glCustom", trap_Cvar_VariableValue("ui_glCustom_store") );
  3084.             trap_Cvar_SetValue( "r_fullscreen",trap_Cvar_VariableValue("r_fullscreen_store") );
  3085.             trap_Cvar_SetValue( "r_allowExtensions", trap_Cvar_VariableValue("r_allowExtensions_store") );
  3086.             trap_Cvar_SetValue( "r_mode", trap_Cvar_VariableValue("r_mode_store") );
  3087.             trap_Cvar_SetValue( "r_colorbits",trap_Cvar_VariableValue("r_colorbits_store") );
  3088.             trap_Cvar_SetValue( "r_lodbias", trap_Cvar_VariableValue("r_lodbias_store") );
  3089.             trap_Cvar_SetValue( "r_picmip", trap_Cvar_VariableValue("r_picmip_store") );
  3090.             trap_Cvar_SetValue( "r_texturebits", trap_Cvar_VariableValue("r_texturebits_store") );
  3091.             trap_Cvar_SetValue( "r_texturemode", trap_Cvar_VariableValue("r_texturemode_store") );
  3092.             trap_Cvar_SetValue( "r_ext_compressed_textures", trap_Cvar_VariableValue("r_ext_compressed_textures_store") ); 
  3093.         }
  3094.         else if (Q_stricmp(name, "orders") == 0) {
  3095.             const char *orders;
  3096.             if (String_Parse(args, &orders)) {
  3097.                 int selectedPlayer = trap_Cvar_VariableValue("cg_selectedPlayer");
  3098.                 if (selectedPlayer < uiInfo.myTeamCount) {
  3099.                     strcpy(buff, orders);
  3100.                     trap_Cmd_ExecuteText( EXEC_APPEND, va(buff, uiInfo.teamClientNums[selectedPlayer]) );
  3101.                     trap_Cmd_ExecuteText( EXEC_APPEND, "\n" );
  3102.                 } else {
  3103.                     int i;
  3104.                     for (i = 0; i < uiInfo.myTeamCount; i++) {
  3105.                         if (Q_stricmp(UI_Cvar_VariableString("name"), uiInfo.teamNames[i]) == 0) {
  3106.                             continue;
  3107.                         }
  3108.                         strcpy(buff, orders);
  3109.                         trap_Cmd_ExecuteText( EXEC_APPEND, va(buff, uiInfo.teamNames[i]) );
  3110.                         trap_Cmd_ExecuteText( EXEC_APPEND, "\n" );
  3111.                     }
  3112.                 }
  3113.                 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );
  3114.                 trap_Key_ClearStates();
  3115.                 trap_Cvar_Set( "cl_paused", "0" );
  3116.                 Menus_CloseAll();
  3117.             }
  3118.         }
  3119.         else if (Q_stricmp(name, "voiceOrdersTeam") == 0) {
  3120.             const char *orders;
  3121.             if (String_Parse(args, &orders)) {
  3122.                 int selectedPlayer = trap_Cvar_VariableValue("cg_selectedPlayer");
  3123.                 if (selectedPlayer == uiInfo.myTeamCount) {
  3124.                     trap_Cmd_ExecuteText( EXEC_APPEND, orders );
  3125.                     trap_Cmd_ExecuteText( EXEC_APPEND, "\n" );
  3126.                 }
  3127.                 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );
  3128.                 trap_Key_ClearStates();
  3129.                 trap_Cvar_Set( "cl_paused", "0" );
  3130.                 Menus_CloseAll();
  3131.             }
  3132.         } else if (Q_stricmp(name, "voiceOrders") == 0) {
  3133.             const char *orders;
  3134.             if (String_Parse(args, &orders)) {
  3135.                 int selectedPlayer = trap_Cvar_VariableValue("cg_selectedPlayer");
  3136.                 if (selectedPlayer < uiInfo.myTeamCount) {
  3137.                     strcpy(buff, orders);
  3138.                     trap_Cmd_ExecuteText( EXEC_APPEND, va(buff, uiInfo.teamClientNums[selectedPlayer]) );
  3139.                     trap_Cmd_ExecuteText( EXEC_APPEND, "\n" );
  3140.                 }
  3141.                 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );
  3142.                 trap_Key_ClearStates();
  3143.                 trap_Cvar_Set( "cl_paused", "0" );
  3144.                 Menus_CloseAll();
  3145.             }
  3146.         }
  3147.         else if (Q_stricmp(name, "RMGRandomSettings") == 0) 
  3148.         {
  3149.             trap_Cvar_Set( "ui_rmg_config", "?" );
  3150.             trap_Cvar_Set( "ui_rmg_time", "?" );                
  3151.             trap_Cvar_Set( "ui_rmg_seed", "?" );                
  3152.         } else if (Q_stricmp(name, "glCustom") == 0) {
  3153.             trap_Cvar_Set("ui_glCustom", "4");
  3154.         } else if (Q_stricmp(name, "update") == 0) {
  3155.             if (String_Parse(args, &name2)) {
  3156.                 UI_Update(name2);
  3157.         }
  3158.         else {
  3159.             Com_Printf("unknown UI script %s\n", name);
  3160.             }
  3161.         }
  3162.     }
  3163. }
  3164.  
  3165. static void UI_GetTeamColor(vec4_t *color) {
  3166. }
  3167.  
  3168. /*
  3169. ==================
  3170. UI_MapCountByGameType
  3171.  
  3172. returns the number of available maps for the netgametype as well as
  3173. marks the active maps active
  3174. ==================
  3175. */
  3176. static int UI_MapCountByGameType( void ) 
  3177. {
  3178.     int i, c, game;
  3179.     c = 0;
  3180.     game = ui_netGameType.integer;
  3181.  
  3182.     for (i = 0; i < uiInfo.mapCount; i++) 
  3183.     {
  3184.         uiInfo.mapList[i].active = qfalse;
  3185.         if ( uiInfo.mapList[i].typeBits & (1 << game)) 
  3186.         {
  3187.             c++;
  3188.             uiInfo.mapList[i].active = qtrue;
  3189.         }
  3190.     }
  3191.     return c;
  3192. }
  3193.  
  3194. /*
  3195. ==================
  3196. UI_MapCountForVote
  3197.  
  3198. returns the number of maps available for a vote
  3199. ==================
  3200. */
  3201. static int UI_MapCountForVote ( void )
  3202. {
  3203.     int i;
  3204.     int    c;
  3205.  
  3206.     c = 0;
  3207.  
  3208.     for (i = 0; i < uiInfo.mapCount; i++) 
  3209.     {
  3210.         uiInfo.mapList[i].active = qfalse;
  3211.  
  3212.         // The random map is prefaced by a *
  3213.         if ( uiInfo.mapList[i].mapLoadName[0] != '*' ) 
  3214.         {
  3215.             c++;
  3216.             uiInfo.mapList[i].active = qtrue;
  3217.         }
  3218.     }
  3219.  
  3220.     return c;
  3221. }
  3222.  
  3223. /*
  3224. ==================
  3225. UI_InsertServerIntoDisplayList
  3226. ==================
  3227. */
  3228. static void UI_InsertServerIntoDisplayList(int num, int position) 
  3229. {
  3230.     int i;
  3231.  
  3232.     if (position < 0 || position > uiInfo.serverStatus.numDisplayServers ) 
  3233.     {
  3234.         return;
  3235.     }
  3236.     
  3237.     uiInfo.serverStatus.numDisplayServers++;
  3238.     for (i = uiInfo.serverStatus.numDisplayServers; i > position; i--) 
  3239.     {
  3240.         uiInfo.serverStatus.displayServers[i] = uiInfo.serverStatus.displayServers[i-1];
  3241.     }
  3242.  
  3243.     uiInfo.serverStatus.displayServers[position] = num;
  3244. }
  3245.  
  3246. /*
  3247. ==================
  3248. UI_RemoveServerFromDisplayList
  3249. ==================
  3250. */
  3251. static void UI_RemoveServerFromDisplayList(int num) {
  3252.     int i, j;
  3253.  
  3254.     for (i = 0; i < uiInfo.serverStatus.numDisplayServers; i++) {
  3255.         if (uiInfo.serverStatus.displayServers[i] == num) {
  3256.             uiInfo.serverStatus.numDisplayServers--;
  3257.             for (j = i; j < uiInfo.serverStatus.numDisplayServers; j++) {
  3258.                 uiInfo.serverStatus.displayServers[j] = uiInfo.serverStatus.displayServers[j+1];
  3259.             }
  3260.             return;
  3261.         }
  3262.     }
  3263. }
  3264.  
  3265. /*
  3266. ==================
  3267. UI_BinaryServerInsertion
  3268. ==================
  3269. */
  3270. static void UI_BinaryServerInsertion(int num) {
  3271.     int mid, offset, res, len;
  3272.  
  3273.     // use binary search to insert server
  3274.     len = uiInfo.serverStatus.numDisplayServers;
  3275.     mid = len;
  3276.     offset = 0;
  3277.     res = 0;
  3278.     while(mid > 0) {
  3279.         mid = len >> 1;
  3280.         //
  3281.         res = trap_LAN_CompareServers( ui_netSource.integer, uiInfo.serverStatus.sortKey,
  3282.                     uiInfo.serverStatus.sortDir, num, uiInfo.serverStatus.displayServers[offset+mid]);
  3283.         // if equal
  3284.         if (res == 0) {
  3285.             UI_InsertServerIntoDisplayList(num, offset+mid);
  3286.             return;
  3287.         }
  3288.         // if larger
  3289.         else if (res == 1) {
  3290.             offset += mid;
  3291.             len -= mid;
  3292.         }
  3293.         // if smaller
  3294.         else {
  3295.             len -= mid;
  3296.         }
  3297.     }
  3298.     if (res == 1) {
  3299.         offset++;
  3300.     }
  3301.     UI_InsertServerIntoDisplayList(num, offset);
  3302. }
  3303.  
  3304. /*
  3305. ==================
  3306. UI_BuildServerDisplayList
  3307. ==================
  3308. */
  3309. static void UI_BuildServerDisplayList(qboolean force) {
  3310.     int i, count, clients, maxClients, ping, game, len, visible;
  3311.     char info[MAX_STRING_CHARS];
  3312. //    qboolean startRefresh = qtrue; TTimo: unused
  3313.     static int numinvisible;
  3314.  
  3315.     if (!(force || uiInfo.uiDC.realTime > uiInfo.serverStatus.nextDisplayRefresh)) {
  3316.         return;
  3317.     }
  3318.     // if we shouldn't reset
  3319.     if ( force == 2 ) {
  3320.         force = 0;
  3321.     }
  3322.  
  3323.     // do motd updates here too
  3324.     trap_Cvar_VariableStringBuffer( "cl_motdString", uiInfo.serverStatus.motd, sizeof(uiInfo.serverStatus.motd) );
  3325.     len = strlen(uiInfo.serverStatus.motd);
  3326.     if (len == 0) {
  3327.         strcpy(uiInfo.serverStatus.motd, "Welcome to Team Arena!");
  3328.         len = strlen(uiInfo.serverStatus.motd);
  3329.     } 
  3330.     if (len != uiInfo.serverStatus.motdLen) {
  3331.         uiInfo.serverStatus.motdLen = len;
  3332.         uiInfo.serverStatus.motdWidth = -1;
  3333.     } 
  3334.  
  3335.     if (force) {
  3336.         numinvisible = 0;
  3337.         // clear number of displayed servers
  3338.         uiInfo.serverStatus.numDisplayServers = 0;
  3339.         uiInfo.serverStatus.numPlayersOnServers = 0;
  3340.         // set list box index to zero
  3341.         Menu_SetFeederSelection(NULL, FEEDER_SERVERS, 0, NULL);
  3342.         // mark all servers as visible so we store ping updates for them
  3343.         trap_LAN_MarkServerVisible(ui_netSource.integer, -1, qtrue);
  3344.     }
  3345.  
  3346.     // get the server count (comes from the master)
  3347.     count = trap_LAN_GetServerCount(ui_netSource.integer);
  3348.     if (count == -1 || (ui_netSource.integer == AS_LOCAL && count == 0) ) {
  3349.         // still waiting on a response from the master
  3350.         uiInfo.serverStatus.numDisplayServers = 0;
  3351.         uiInfo.serverStatus.numPlayersOnServers = 0;
  3352.         uiInfo.serverStatus.nextDisplayRefresh = uiInfo.uiDC.realTime + 500;
  3353.         return;
  3354.     }
  3355.  
  3356.     visible = qfalse;
  3357.     for (i = 0; i < count; i++) {
  3358.         // if we already got info for this server
  3359.         if (!trap_LAN_ServerIsVisible(ui_netSource.integer, i)) {
  3360.             continue;
  3361.         }
  3362.         visible = qtrue;
  3363.         // get the ping for this server
  3364.         ping = trap_LAN_GetServerPing(ui_netSource.integer, i);
  3365.         if (ping > 0 || ui_netSource.integer == AS_FAVORITES) {
  3366.  
  3367.             trap_LAN_GetServerInfo(ui_netSource.integer, i, info, MAX_STRING_CHARS);
  3368.  
  3369.             clients = atoi(Info_ValueForKey(info, "clients"));
  3370.             uiInfo.serverStatus.numPlayersOnServers += clients;
  3371.  
  3372.             if (ui_browserShowEmpty.integer == 0) {
  3373.                 if (clients == 0) {
  3374.                     trap_LAN_MarkServerVisible(ui_netSource.integer, i, qfalse);
  3375.                     continue;
  3376.                 }
  3377.             }
  3378.  
  3379.             if (ui_browserShowFull.integer == 0) {
  3380.                 maxClients = atoi(Info_ValueForKey(info, "sv_maxclients"));
  3381.                 if (clients == maxClients) {
  3382.                     trap_LAN_MarkServerVisible(ui_netSource.integer, i, qfalse);
  3383.                     continue;
  3384.                 }
  3385.             }
  3386.  
  3387.             if ( ui_joinGameType.integer != 0) 
  3388.             {
  3389.                 game = BG_FindGametype(Info_ValueForKey(info, "gametype"));
  3390.                 
  3391.                 if (game != ui_joinGameType.integer - 1 ) 
  3392.                 {
  3393.                     trap_LAN_MarkServerVisible( ui_netSource.integer, i, qfalse);
  3394.                     continue;
  3395.                 }
  3396.             }
  3397.                 
  3398.             if (ui_serverFilterType.integer > 0) {
  3399.                 if (Q_stricmp(Info_ValueForKey(info, "game"), serverFilters[ui_serverFilterType.integer].basedir) != 0) {
  3400.                     trap_LAN_MarkServerVisible(ui_netSource.integer, i, qfalse);
  3401.                     continue;
  3402.                 }
  3403.             }
  3404.             // make sure we never add a favorite server twice
  3405.             if (ui_netSource.integer == AS_FAVORITES) {
  3406.                 UI_RemoveServerFromDisplayList(i);
  3407.             }
  3408.             // insert the server into the list
  3409.             UI_BinaryServerInsertion(i);
  3410.             // done with this server
  3411.             if (ping > 0) {
  3412.                 trap_LAN_MarkServerVisible(ui_netSource.integer, i, qfalse);
  3413.                 numinvisible++;
  3414.             }
  3415.         }
  3416.     }
  3417.  
  3418.     uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime;
  3419.  
  3420.     // if there were no servers visible for ping updates
  3421.     if (!visible) {
  3422. //        UI_StopServerRefresh();
  3423. //        uiInfo.serverStatus.nextDisplayRefresh = 0;
  3424.     }
  3425. }
  3426.  
  3427. typedef struct
  3428. {
  3429.     char    *name;
  3430.     char    *altName;
  3431.  
  3432. } serverStatusCvar_t;
  3433.  
  3434. serverStatusCvar_t serverStatusCvars[] = 
  3435. {
  3436.     {"sv_hostname",        "Name"        },
  3437.     {"Address",            ""            },
  3438.     {"gamename",        "Game name"    },
  3439.     {"g_gametype",        "Game type"    },
  3440.     {"mapname",            "Map"        },
  3441.     {"version",            ""            },
  3442.     {"protocol",        ""            },
  3443.     {"timelimit",        ""            },
  3444.     {"scorelimit",        ""            },
  3445.     {NULL, NULL}
  3446. };
  3447.  
  3448. /*
  3449. ==================
  3450. UI_SortServerStatusInfo
  3451. ==================
  3452. */
  3453. static void UI_SortServerStatusInfo( serverStatusInfo_t *info ) 
  3454. {
  3455.     int i, j, index;
  3456.     char *tmp1, *tmp2;
  3457.  
  3458.     index = 0;
  3459.     for (i = 0; serverStatusCvars[i].name; i++) 
  3460.     {
  3461.         for (j = 0; j < info->numLines; j++) 
  3462.         {
  3463.             if ( !info->lines[j][1] || info->lines[j][1][0] ) 
  3464.             {
  3465.                 continue;
  3466.             }
  3467.  
  3468.             if ( !Q_stricmp(serverStatusCvars[i].name, info->lines[j][0]) ) 
  3469.             {
  3470.                 // swap lines
  3471.                 tmp1 = info->lines[index][0];
  3472.                 tmp2 = info->lines[index][3];
  3473.                 info->lines[index][0] = info->lines[j][0];
  3474.                 info->lines[index][3] = info->lines[j][3];
  3475.                 info->lines[j][0] = tmp1;
  3476.                 info->lines[j][3] = tmp2;
  3477.                 
  3478.                 //
  3479.                 if ( strlen(serverStatusCvars[i].altName) ) 
  3480.                 {
  3481.                     info->lines[index][0] = serverStatusCvars[i].altName;
  3482.                 }
  3483.                 index++;
  3484.             }
  3485.         }
  3486.     }
  3487. }
  3488.  
  3489. /*
  3490. ==================
  3491. UI_GetServerStatusInfo
  3492. ==================
  3493. */
  3494. static int UI_GetServerStatusInfo( const char *serverAddress, serverStatusInfo_t *info ) {
  3495.     char *p, *score, *ping, *name, *team;
  3496.     int i, len;
  3497.  
  3498.     if (!info) {
  3499.         trap_LAN_ServerStatus( serverAddress, NULL, 0);
  3500.         return qfalse;
  3501.     }
  3502.     memset(info, 0, sizeof(*info));
  3503.     if ( trap_LAN_ServerStatus( serverAddress, info->text, sizeof(info->text)) ) {
  3504.         Q_strncpyz(info->address, serverAddress, sizeof(info->address));
  3505.         p = info->text;
  3506.         info->numLines = 0;
  3507.         info->lines[info->numLines][0] = "Address";
  3508.         info->lines[info->numLines][1] = "";
  3509.         info->lines[info->numLines][2] = "";
  3510.         info->lines[info->numLines][3] = info->address;
  3511.         info->numLines++;
  3512.         // get the cvars
  3513.         while (p && *p) {
  3514.             p = strchr(p, '\\');
  3515.             if (!p) break;
  3516.             *p++ = '\0';
  3517.             if (*p == '\\')
  3518.                 break;
  3519.             info->lines[info->numLines][0] = p;
  3520.             info->lines[info->numLines][1] = "";
  3521.             info->lines[info->numLines][2] = "";
  3522.             p = strchr(p, '\\');
  3523.             if (!p) break;
  3524.             *p++ = '\0';
  3525.             info->lines[info->numLines][3] = p;
  3526.  
  3527.             info->numLines++;
  3528.             if (info->numLines >= MAX_SERVERSTATUS_LINES)
  3529.                 break;
  3530.         }
  3531.         // get the player list
  3532.         if (info->numLines < MAX_SERVERSTATUS_LINES-3) {
  3533.             // empty line
  3534.             info->lines[info->numLines][0] = "";
  3535.             info->lines[info->numLines][1] = "";
  3536.             info->lines[info->numLines][2] = "";
  3537.             info->lines[info->numLines][3] = "";
  3538.             info->numLines++;
  3539.             // header
  3540.             info->lines[info->numLines][0] = "num";
  3541.             info->lines[info->numLines][1] = "score";
  3542.             info->lines[info->numLines][2] = "ping";
  3543.             info->lines[info->numLines][3] = "name";
  3544.             info->numLines++;
  3545.             // parse players
  3546.             i = 0;
  3547.             len = 0;
  3548.             while (p && *p) {
  3549.                 if (*p == '\\')
  3550.                     *p++ = '\0';
  3551.                 if (!p)
  3552.                     break;
  3553.                 score = p;
  3554.                 p = strchr(p, ' ');
  3555.                 if (!p)
  3556.                     break;
  3557.                 *p++ = '\0';
  3558.                 ping = p;
  3559.                 p = strchr(p, ' ');
  3560.                 if (!p)
  3561.                     break;
  3562.                 *p++ = '\0';
  3563.                 team = p;
  3564.                 p = strchr(p, ' ');
  3565.                 if (!p)
  3566.                     break;
  3567.                 *p++ = '\0';
  3568.                 name = p;
  3569.                 Com_sprintf(&info->pings[len], sizeof(info->pings)-len, "%d", i);
  3570.                 info->lines[info->numLines][0] = &info->pings[len];
  3571.                 len += strlen(&info->pings[len]) + 1;
  3572.                 info->lines[info->numLines][1] = score;
  3573.                 info->lines[info->numLines][2] = ping;
  3574.                 info->lines[info->numLines][3] = name;
  3575.                 info->numLines++;
  3576.                 if (info->numLines >= MAX_SERVERSTATUS_LINES)
  3577.                     break;
  3578.                 p = strchr(p, '\\');
  3579.                 if (!p)
  3580.                     break;
  3581.                 *p++ = '\0';
  3582.                 //
  3583.                 i++;
  3584.             }
  3585.         }
  3586.         UI_SortServerStatusInfo( info );
  3587.         return qtrue;
  3588.     }
  3589.     return qfalse;
  3590. }
  3591.  
  3592. /*
  3593. ==================
  3594. stristr
  3595. ==================
  3596. */
  3597. static char *stristr(char *str, char *charset) {
  3598.     int i;
  3599.  
  3600.     while(*str) {
  3601.         for (i = 0; charset[i] && str[i]; i++) {
  3602.             if (toupper(charset[i]) != toupper(str[i])) break;
  3603.         }
  3604.         if (!charset[i]) return str;
  3605.         str++;
  3606.     }
  3607.     return NULL;
  3608. }
  3609.  
  3610. /*
  3611. ==================
  3612. UI_BuildFindPlayerList
  3613. ==================
  3614. */
  3615. static void UI_BuildFindPlayerList(qboolean force) {
  3616.     static int numFound, numTimeOuts;
  3617.     int i, j, resend;
  3618.     serverStatusInfo_t info;
  3619.     char name[MAX_NAME_LENGTH+2];
  3620.     char infoString[MAX_STRING_CHARS];
  3621.  
  3622.     if (!force) {
  3623.         if (!uiInfo.nextFindPlayerRefresh || uiInfo.nextFindPlayerRefresh > uiInfo.uiDC.realTime) {
  3624.             return;
  3625.         }
  3626.     }
  3627.     else {
  3628.         memset(&uiInfo.pendingServerStatus, 0, sizeof(uiInfo.pendingServerStatus));
  3629.         uiInfo.numFoundPlayerServers = 0;
  3630.         uiInfo.currentFoundPlayerServer = 0;
  3631.         trap_Cvar_VariableStringBuffer( "ui_findPlayer", uiInfo.findPlayerName, sizeof(uiInfo.findPlayerName));
  3632.         Q_CleanStr(uiInfo.findPlayerName);
  3633.         // should have a string of some length
  3634.         if (!strlen(uiInfo.findPlayerName)) {
  3635.             uiInfo.nextFindPlayerRefresh = 0;
  3636.             return;
  3637.         }
  3638.         // set resend time
  3639.         resend = ui_serverStatusTimeOut.integer / 2 - 10;
  3640.         if (resend < 50) {
  3641.             resend = 50;
  3642.         }
  3643.         trap_Cvar_Set("cl_serverStatusResendTime", va("%d", resend));
  3644.         // reset all server status requests
  3645.         trap_LAN_ServerStatus( NULL, NULL, 0);
  3646.         //
  3647.         uiInfo.numFoundPlayerServers = 1;
  3648.         Com_sprintf(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1],
  3649.                         sizeof(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1]),
  3650.                             "searching %d...", uiInfo.pendingServerStatus.num);
  3651.         numFound = 0;
  3652.         numTimeOuts++;
  3653.     }
  3654.     for (i = 0; i < MAX_SERVERSTATUSREQUESTS; i++) {
  3655.         // if this pending server is valid
  3656.         if (uiInfo.pendingServerStatus.server[i].valid) {
  3657.             // try to get the server status for this server
  3658.             if (UI_GetServerStatusInfo( uiInfo.pendingServerStatus.server[i].adrstr, &info ) ) {
  3659.                 //
  3660.                 numFound++;
  3661.                 // parse through the server status lines
  3662.                 for (j = 0; j < info.numLines; j++) {
  3663.                     // should have ping info
  3664.                     if ( !info.lines[j][2] || !info.lines[j][2][0] ) {
  3665.                         continue;
  3666.                     }
  3667.                     // clean string first
  3668.                     Q_strncpyz(name, info.lines[j][3], sizeof(name));
  3669.                     Q_CleanStr(name);
  3670.                     // if the player name is a substring
  3671.                     if (stristr(name, uiInfo.findPlayerName)) {
  3672.                         // add to found server list if we have space (always leave space for a line with the number found)
  3673.                         if (uiInfo.numFoundPlayerServers < MAX_FOUNDPLAYER_SERVERS-1) {
  3674.                             //
  3675.                             Q_strncpyz(uiInfo.foundPlayerServerAddresses[uiInfo.numFoundPlayerServers-1],
  3676.                                         uiInfo.pendingServerStatus.server[i].adrstr,
  3677.                                             sizeof(uiInfo.foundPlayerServerAddresses[0]));
  3678.                             Q_strncpyz(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1],
  3679.                                         uiInfo.pendingServerStatus.server[i].name,
  3680.                                             sizeof(uiInfo.foundPlayerServerNames[0]));
  3681.                             uiInfo.numFoundPlayerServers++;
  3682.                         }
  3683.                         else {
  3684.                             // can't add any more so we're done
  3685.                             uiInfo.pendingServerStatus.num = uiInfo.serverStatus.numDisplayServers;
  3686.                         }
  3687.                     }
  3688.                 }
  3689.                 Com_sprintf(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1],
  3690.                                 sizeof(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1]),
  3691.                                     "searching %d/%d...", uiInfo.pendingServerStatus.num, numFound);
  3692.                 // retrieved the server status so reuse this spot
  3693.                 uiInfo.pendingServerStatus.server[i].valid = qfalse;
  3694.             }
  3695.         }
  3696.         // if empty pending slot or timed out
  3697.         if (!uiInfo.pendingServerStatus.server[i].valid ||
  3698.             uiInfo.pendingServerStatus.server[i].startTime < uiInfo.uiDC.realTime - ui_serverStatusTimeOut.integer) {
  3699.             if (uiInfo.pendingServerStatus.server[i].valid) {
  3700.                 numTimeOuts++;
  3701.             }
  3702.             // reset server status request for this address
  3703.             UI_GetServerStatusInfo( uiInfo.pendingServerStatus.server[i].adrstr, NULL );
  3704.             // reuse pending slot
  3705.             uiInfo.pendingServerStatus.server[i].valid = qfalse;
  3706.             // if we didn't try to get the status of all servers in the main browser yet
  3707.             if (uiInfo.pendingServerStatus.num < uiInfo.serverStatus.numDisplayServers) {
  3708.                 uiInfo.pendingServerStatus.server[i].startTime = uiInfo.uiDC.realTime;
  3709.                 trap_LAN_GetServerAddressString(ui_netSource.integer, uiInfo.serverStatus.displayServers[uiInfo.pendingServerStatus.num],
  3710.                             uiInfo.pendingServerStatus.server[i].adrstr, sizeof(uiInfo.pendingServerStatus.server[i].adrstr));
  3711.                 trap_LAN_GetServerInfo(ui_netSource.integer, uiInfo.serverStatus.displayServers[uiInfo.pendingServerStatus.num], infoString, sizeof(infoString));
  3712.                 Q_strncpyz(uiInfo.pendingServerStatus.server[i].name, Info_ValueForKey(infoString, "hostname"), sizeof(uiInfo.pendingServerStatus.server[0].name));
  3713.                 uiInfo.pendingServerStatus.server[i].valid = qtrue;
  3714.                 uiInfo.pendingServerStatus.num++;
  3715.                 Com_sprintf(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1],
  3716.                                 sizeof(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1]),
  3717.                                     "searching %d/%d...", uiInfo.pendingServerStatus.num, numFound);
  3718.             }
  3719.         }
  3720.     }
  3721.     for (i = 0; i < MAX_SERVERSTATUSREQUESTS; i++) {
  3722.         if (uiInfo.pendingServerStatus.server[i].valid) {
  3723.             break;
  3724.         }
  3725.     }
  3726.     // if still trying to retrieve server status info
  3727.     if (i < MAX_SERVERSTATUSREQUESTS) {
  3728.         uiInfo.nextFindPlayerRefresh = uiInfo.uiDC.realTime + 25;
  3729.     }
  3730.     else {
  3731.         // add a line that shows the number of servers found
  3732.         if (!uiInfo.numFoundPlayerServers) {
  3733.             Com_sprintf(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1], sizeof(uiInfo.foundPlayerServerAddresses[0]), "no servers found");
  3734.         }
  3735.         else {
  3736.             Com_sprintf(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1], sizeof(uiInfo.foundPlayerServerAddresses[0]),
  3737.                         "%d server%s found for player", uiInfo.numFoundPlayerServers-1,
  3738.                         uiInfo.numFoundPlayerServers == 2 ? "":"s");
  3739.         }
  3740.         uiInfo.nextFindPlayerRefresh = 0;
  3741.         // show the server status info for the selected server
  3742.         UI_FeederSelection(FEEDER_FINDPLAYER, uiInfo.currentFoundPlayerServer);
  3743.     }
  3744. }
  3745.  
  3746. /*
  3747. ==================
  3748. UI_BuildServerStatus
  3749. ==================
  3750. */
  3751. static void UI_BuildServerStatus(qboolean force) {
  3752.  
  3753.     if (uiInfo.nextFindPlayerRefresh) {
  3754.         return;
  3755.     }
  3756.     if (!force) {
  3757.         if (!uiInfo.nextServerStatusRefresh || uiInfo.nextServerStatusRefresh > uiInfo.uiDC.realTime) {
  3758.             return;
  3759.         }
  3760.     }
  3761.     else {
  3762.         Menu_SetFeederSelection(NULL, FEEDER_SERVERSTATUS, 0, NULL);
  3763.         uiInfo.serverStatusInfo.numLines = 0;
  3764.         // reset all server status requests
  3765.         trap_LAN_ServerStatus( NULL, NULL, 0);
  3766.     }
  3767.     if (uiInfo.serverStatus.currentServer < 0 || uiInfo.serverStatus.currentServer > uiInfo.serverStatus.numDisplayServers || uiInfo.serverStatus.numDisplayServers == 0) {
  3768.         return;
  3769.     }
  3770.     if (UI_GetServerStatusInfo( uiInfo.serverStatusAddress, &uiInfo.serverStatusInfo ) ) {
  3771.         uiInfo.nextServerStatusRefresh = 0;
  3772.         UI_GetServerStatusInfo( uiInfo.serverStatusAddress, NULL );
  3773.     }
  3774.     else {
  3775.         uiInfo.nextServerStatusRefresh = uiInfo.uiDC.realTime + 500;
  3776.     }
  3777. }
  3778.  
  3779. /*
  3780. ==================
  3781. UI_FeederCount
  3782. ==================
  3783. */
  3784. static int UI_FeederCount(float feederID) 
  3785. {
  3786.     switch ( (int)feederID )
  3787.     {
  3788.         case FEEDER_IDENTITIES:
  3789.             return bg_identityCount;
  3790.  
  3791.         case FEEDER_TEAMIDENTITIES:
  3792.         {
  3793.             int        count;
  3794.             team_t    team;
  3795.  
  3796.             team = ui_info_team.integer;
  3797.             if ( team != TEAM_RED && team != TEAM_BLUE )
  3798.             {    
  3799.                 return 0;
  3800.             }
  3801.  
  3802.             for ( count = 0; count < MAX_TEAMIDENTITIES; count ++ )
  3803.             {
  3804.                 if ( !uiInfo.identityTeams[team][count] )
  3805.                     break;
  3806.             }
  3807.  
  3808.             return count;
  3809.         }
  3810.  
  3811.         case FEEDER_CINEMATICS:
  3812.             return uiInfo.movieCount;
  3813.  
  3814.         case FEEDER_MAPS:
  3815.         case FEEDER_ALLMAPS:
  3816.             return UI_MapCountByGameType ();
  3817.  
  3818.         case FEEDER_VOTEMAPS:
  3819.             return UI_MapCountForVote ( );
  3820.  
  3821.         case FEEDER_OUTFITTING_TEMPLATES:
  3822.             return bg_outfittingCount;
  3823.  
  3824.         case FEEDER_SERVERS:
  3825.             return uiInfo.serverStatus.numDisplayServers;
  3826.  
  3827.         case FEEDER_SERVERSTATUS:
  3828.             return uiInfo.serverStatusInfo.numLines;
  3829.  
  3830.         case FEEDER_FINDPLAYER:
  3831.             return uiInfo.numFoundPlayerServers;
  3832.  
  3833.         case FEEDER_NEWVERSION_WEBSITES:
  3834.             return trap_Version_GetNumSites();
  3835.  
  3836.         case FEEDER_PLAYER_LIST:
  3837.             if (uiInfo.uiDC.realTime > uiInfo.playerRefresh) 
  3838.             {
  3839.                 uiInfo.playerRefresh = uiInfo.uiDC.realTime + 3000;
  3840.                 UI_BuildPlayerList();
  3841.             }
  3842.             return uiInfo.playerCount;
  3843.  
  3844.         case FEEDER_MODS:
  3845.             return uiInfo.modCount;
  3846.  
  3847.         case FEEDER_DEMOS:
  3848.             return uiInfo.demoCount;
  3849.     }
  3850.     
  3851.     return 0;
  3852. }
  3853.  
  3854. static const char *UI_SelectedMap(int index, int *actual) 
  3855. {
  3856.     int i, c;
  3857.     c = 0;
  3858.     *actual = 0;
  3859.  
  3860.     for (i = 0; i < uiInfo.mapCount; i++) 
  3861.     {
  3862.         if (uiInfo.mapList[i].active) 
  3863.         {
  3864.             if (c == index) 
  3865.             {
  3866.                 *actual = i;
  3867.                 return uiInfo.mapList[i].mapName;
  3868.             } 
  3869.             else 
  3870.             {
  3871.                 c++;
  3872.             }
  3873.         }
  3874.     }
  3875.     
  3876.     return "";
  3877. }
  3878.  
  3879. static int UI_GetIndexFromSelection ( int actual ) 
  3880. {
  3881.     int i;
  3882.     int    c;
  3883.  
  3884.     for ( c = 0, i = 0; i < uiInfo.mapCount; i++) 
  3885.     {
  3886.         if (uiInfo.mapList[i].active) 
  3887.         {
  3888.             if (i == actual) 
  3889.             {
  3890.                 return c;
  3891.             }
  3892.             
  3893.             c++;
  3894.         }
  3895.     }
  3896.  
  3897.     return 0;
  3898. }
  3899.  
  3900. static void UI_UpdatePendingPings() { 
  3901.     trap_LAN_ResetPings(ui_netSource.integer);
  3902.     uiInfo.serverStatus.refreshActive = qtrue;
  3903.     uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime + 1000;
  3904.  
  3905. }
  3906.  
  3907.  
  3908. static const char *UI_FeederItemText(float feederID, int index, int column, qhandle_t *handle) 
  3909. {
  3910.     static char info[MAX_STRING_CHARS];
  3911.     static char info2[MAX_STRING_CHARS];
  3912.     static char hostname[MAX_STRING_CHARS];
  3913.     static char needpass[2];
  3914.     static char clientBuff[32];
  3915.     static int    lastColumn = -1;
  3916.     static int    lastTime = 0;
  3917.  
  3918.     *handle = -1;
  3919.  
  3920.     switch ( (int)feederID )
  3921.     {
  3922.         case FEEDER_IDENTITIES:
  3923.             if (index >= 0 && index < bg_identityCount) 
  3924.             {
  3925.                 return bg_identities[index].mName;
  3926.             }
  3927.             break;
  3928.  
  3929.         case FEEDER_TEAMIDENTITIES:
  3930.             if ( index >= 0 && index < MAX_TEAMIDENTITIES )
  3931.             {
  3932.                 return uiInfo.identityTeams[ui_info_team.integer][index]->mName;
  3933.             }
  3934.             break;
  3935.  
  3936.         case FEEDER_MAPS:
  3937.         case FEEDER_ALLMAPS:
  3938.         case FEEDER_VOTEMAPS:
  3939.         {
  3940.             int actual;
  3941.             return UI_SelectedMap(index, &actual);
  3942.         }
  3943.  
  3944.         case FEEDER_OUTFITTING_TEMPLATES:
  3945.             return bg_outfittings[index].name;
  3946.  
  3947.         case FEEDER_NEWVERSION_TEXT:
  3948.             trap_Version_GetDescription(info2, sizeof(info2));
  3949.             return info2;
  3950.  
  3951.         case FEEDER_NEWVERSION_WEBSITES:
  3952.             trap_Version_GetSite(index, info, sizeof(info));
  3953.             return info;
  3954.  
  3955.         case FEEDER_SERVERS:
  3956.             if (index >= 0 && index < uiInfo.serverStatus.numDisplayServers) 
  3957.             {
  3958.                 int ping;
  3959.                 int game;
  3960.                 
  3961.                 if (lastColumn != column || lastTime > uiInfo.uiDC.realTime + 5000) 
  3962.                 {
  3963.                     trap_LAN_GetServerInfo(ui_netSource.integer, uiInfo.serverStatus.displayServers[index], info, MAX_STRING_CHARS);
  3964.                     lastColumn = column;
  3965.                     lastTime = uiInfo.uiDC.realTime;
  3966.                 }
  3967.                 
  3968.                 ping = atoi(Info_ValueForKey(info, "ping"));
  3969.                 if (ping == -1) 
  3970.                 {
  3971.                     // if we ever see a ping that is out of date, do a server refresh
  3972.                     // UI_UpdatePendingPings();
  3973.                 }
  3974.             
  3975.                 switch (column) 
  3976.                 {
  3977.                     case SORT_NEEDPASS:
  3978.                         needpass[0] = atoi(Info_ValueForKey(info, "needpass"))?'*':' ';
  3979.                         needpass[1] = 0;
  3980.                         return needpass;
  3981.  
  3982.                     case SORT_HOST : 
  3983.                         if (ping <= 0) 
  3984.                         {
  3985.                             return Info_ValueForKey(info, "addr");
  3986.                         } 
  3987.                         else 
  3988.                         {
  3989.                             if ( ui_netSource.integer == AS_LOCAL ) 
  3990.                             {
  3991.                                 Com_sprintf( hostname, sizeof(hostname), "[%s] %s",
  3992.                                              netnames[atoi(Info_ValueForKey(info, "nettype"))],
  3993.                                              Info_ValueForKey(info, "hostname") );
  3994.                                 return hostname;
  3995.                             }
  3996.                             else
  3997.                             {
  3998.                                 // anonymous server
  3999.                                 if (atoi(Info_ValueForKey(info, "sv_allowAnonymous")) != 0)
  4000.                                 {                
  4001.                                     Com_sprintf( hostname, sizeof(hostname), "(A) %s",
  4002.                                                  Info_ValueForKey(info, "hostname"));
  4003.                                 } 
  4004.                                 else 
  4005.                                 {
  4006.                                     Com_sprintf( hostname, sizeof(hostname), "%s",
  4007.                                                  Info_ValueForKey(info, "hostname"));
  4008.                                 }
  4009.                             }
  4010.                         
  4011.                             return hostname;
  4012.                         }
  4013.  
  4014.                         break;
  4015.  
  4016.                     case SORT_MAP : 
  4017.                         return Info_ValueForKey(info, "mapname");
  4018.  
  4019.                     case SORT_CLIENTS : 
  4020.                         Com_sprintf( clientBuff, sizeof(clientBuff), "%s (%s)", Info_ValueForKey(info, "clients"), Info_ValueForKey(info, "sv_maxclients"));
  4021.                         return clientBuff;
  4022.                 
  4023.                     case SORT_GAME :
  4024.                         game = BG_FindGametype ( Info_ValueForKey(info, "gametype") );
  4025.                         if (ping <= 0)
  4026.                         {
  4027.                             return "Inactive";    
  4028.                         }
  4029.                         else if (game < 0) 
  4030.                         {
  4031.                             return "Unknown";    
  4032.                         } 
  4033.  
  4034.                         return bg_gametypeData[game].name;
  4035.  
  4036.                     case SORT_PING : 
  4037.                         if (ping <= 0) 
  4038.                         {
  4039.                             return "...";
  4040.                         } 
  4041.  
  4042.                         return Info_ValueForKey(info, "ping");
  4043.                 }
  4044.             }
  4045.  
  4046.             break;
  4047.  
  4048.         case FEEDER_SERVERSTATUS:
  4049.  
  4050.             if ( index >= 0 && index < uiInfo.serverStatusInfo.numLines ) 
  4051.             {
  4052.                 if ( column >= 0 && column < 4 ) 
  4053.                 {
  4054.                     return uiInfo.serverStatusInfo.lines[index][column];
  4055.                 }
  4056.             }
  4057.             break;
  4058.  
  4059.         case FEEDER_FINDPLAYER:
  4060.             if ( index >= 0 && index < uiInfo.numFoundPlayerServers ) 
  4061.             {
  4062.                 return uiInfo.foundPlayerServerNames[index];
  4063.             }
  4064.             break;
  4065.  
  4066.         case FEEDER_PLAYER_LIST:
  4067.             if (index >= 0 && index < uiInfo.playerCount) 
  4068.             {
  4069.                 return uiInfo.playerNames[index] + 2;
  4070.             }
  4071.             break;
  4072.     
  4073.         case FEEDER_MODS:
  4074.             if (index >= 0 && index < uiInfo.modCount) 
  4075.             {
  4076.                 if (uiInfo.modList[index].modDescr && *uiInfo.modList[index].modDescr) 
  4077.                 {
  4078.                     return uiInfo.modList[index].modDescr;
  4079.                 } 
  4080.                 else 
  4081.                 {
  4082.                     return uiInfo.modList[index].modName;
  4083.                 }
  4084.             }
  4085.             break;
  4086.  
  4087.         case FEEDER_CINEMATICS:
  4088.             if (index >= 0 && index < uiInfo.movieCount) 
  4089.             {
  4090.                 return uiInfo.movieList[index];
  4091.             }
  4092.             break;
  4093.     
  4094.         case FEEDER_DEMOS:
  4095.             if (index >= 0 && index < uiInfo.demoCount) 
  4096.             {
  4097.                 return uiInfo.demoList[index];
  4098.             }
  4099.             break;
  4100.     }
  4101.     
  4102.     return "";
  4103. }
  4104.  
  4105. static qhandle_t UI_FeederItemImage ( float feederID, int index ) 
  4106. {
  4107.     switch ( (int)feederID )
  4108.     {
  4109.         case FEEDER_IDENTITIES:
  4110.             if (index >= 0 && index < bg_identityCount) 
  4111.             {
  4112.                 return bg_identities[index].mIcon;
  4113.             }
  4114.             break;
  4115.  
  4116.         case FEEDER_TEAMIDENTITIES:
  4117.             if (index >= 0 && index < MAX_TEAMIDENTITIES) 
  4118.             {
  4119.                 return uiInfo.identityTeams[ui_info_team.integer][index]->mIcon;
  4120.             }
  4121.             break;
  4122.  
  4123.         case FEEDER_ALLMAPS:
  4124.         case FEEDER_MAPS:
  4125.         case FEEDER_VOTEMAPS:
  4126.         {
  4127.             int actual;
  4128.             
  4129.             UI_SelectedMap(index, &actual);
  4130.             index = actual;
  4131.             
  4132.             if (index >= 0 && index < uiInfo.mapCount) 
  4133.             {
  4134.                 if (uiInfo.mapList[index].levelShot == -1) 
  4135.                 {
  4136.                     uiInfo.mapList[index].levelShot = trap_R_RegisterShaderNoMip(uiInfo.mapList[index].imageName);
  4137.                 }
  4138.                 return uiInfo.mapList[index].levelShot;
  4139.             }
  4140.  
  4141.             break;
  4142.         }
  4143.     }
  4144.   
  4145.     return 0;
  4146. }
  4147.  
  4148. static void UI_FeederSelection(float feederID, int index) 
  4149. {
  4150.     static char info[MAX_STRING_CHARS];
  4151.     
  4152.     switch ( (int)feederID )
  4153.     {
  4154.         case FEEDER_OUTFITTING_TEMPLATES:
  4155.             uiInfo.outfittingItemGroup = index;
  4156.             break;
  4157.     
  4158.         case FEEDER_IDENTITIES:
  4159.             if (index >= 0 && index < bg_identityCount) 
  4160.             {
  4161.                 trap_Cvar_Set( "identity", bg_identities[index].mName);
  4162.                 updateModel = qtrue;
  4163.             }
  4164.             break;
  4165.  
  4166.         case FEEDER_TEAMIDENTITIES:
  4167.             if (index >= 0 && index < MAX_TEAMIDENTITIES) 
  4168.             {
  4169.                 trap_Cvar_Set( "team_identity", uiInfo.identityTeams[ui_info_team.integer][index]->mName );
  4170.                 updateModel = qtrue;
  4171.             }
  4172.             break;
  4173.  
  4174.         case FEEDER_MAPS:
  4175.         case FEEDER_ALLMAPS:
  4176.         case FEEDER_VOTEMAPS:
  4177.         {
  4178.             int actual, map;
  4179.             map = (feederID == FEEDER_ALLMAPS) ? ui_currentNetMap.integer : ui_currentMap.integer;
  4180.             if (uiInfo.mapList[map].cinematic >= 0) 
  4181.             {
  4182.                 trap_CIN_StopCinematic(uiInfo.mapList[map].cinematic);
  4183.                 uiInfo.mapList[map].cinematic = -1;
  4184.             }
  4185.             
  4186.             if ( *UI_SelectedMap(index, &actual) )
  4187.             {
  4188.                 trap_Cvar_Set("ui_mapIndex", va("%d", index));
  4189.                 ui_mapIndex.integer = index;
  4190.  
  4191.                 if (feederID == FEEDER_MAPS) 
  4192.                 {
  4193.                     ui_currentMap.integer = actual;
  4194.                     trap_Cvar_Set("ui_currentMap", va("%d", actual));
  4195.                       uiInfo.mapList[ui_currentMap.integer].cinematic = trap_CIN_PlayCinematic(va("%s.roq", uiInfo.mapList[ui_currentMap.integer].mapLoadName), 0, 0, 0, 0, (CIN_loop | CIN_silent) );
  4196.                     trap_Cvar_Set("ui_opponentModel", uiInfo.mapList[ui_currentMap.integer].opponentName);
  4197.                 } 
  4198.                 else 
  4199.                 {
  4200.                     ui_currentNetMap.integer = actual;
  4201.                     trap_Cvar_Set("ui_currentNetMap", va("%d", actual));
  4202.                     trap_Cvar_Set("ui_currentNetMapName", uiInfo.mapList[actual].mapLoadName );
  4203.                       uiInfo.mapList[ui_currentNetMap.integer].cinematic = trap_CIN_PlayCinematic(va("%s.roq", uiInfo.mapList[ui_currentNetMap.integer].mapLoadName), 0, 0, 0, 0, (CIN_loop | CIN_silent) );
  4204.                 }
  4205.             }
  4206.             break;
  4207.         }
  4208.  
  4209.         case FEEDER_NEWVERSION_WEBSITES:
  4210.             uiInfo.versionIndex = index;
  4211.             break;
  4212.  
  4213.         case FEEDER_SERVERS:
  4214.         {
  4215.             const char *mapName = NULL;
  4216.             uiInfo.serverStatus.currentServer = index;
  4217.             trap_LAN_GetServerInfo(ui_netSource.integer, uiInfo.serverStatus.displayServers[index], info, MAX_STRING_CHARS);
  4218.             uiInfo.serverStatus.currentServerPreview = trap_R_RegisterShaderNoMip(va("gfx/menus/levelshots/%s", Info_ValueForKey(info, "mapname")));
  4219.             if (uiInfo.serverStatus.currentServerCinematic >= 0) 
  4220.             {
  4221.                 trap_CIN_StopCinematic( uiInfo.serverStatus.currentServerCinematic);
  4222.                 uiInfo.serverStatus.currentServerCinematic = -1;
  4223.             }
  4224.             mapName = Info_ValueForKey(info, "mapname");
  4225.             if (mapName && *mapName) 
  4226.             {
  4227.                 uiInfo.serverStatus.currentServerCinematic = trap_CIN_PlayCinematic(va("%s.roq", mapName), 0, 0, 0, 0, (CIN_loop | CIN_silent) );
  4228.             }
  4229.             break;
  4230.         }
  4231.  
  4232.         case FEEDER_FINDPLAYER:
  4233.             uiInfo.currentFoundPlayerServer = index;
  4234.  
  4235.             if ( index < uiInfo.numFoundPlayerServers-1) 
  4236.             {
  4237.                 // build a new server status for this server
  4238.                 Q_strncpyz(uiInfo.serverStatusAddress, uiInfo.foundPlayerServerAddresses[uiInfo.currentFoundPlayerServer], sizeof(uiInfo.serverStatusAddress));
  4239.                 Menu_SetFeederSelection(NULL, FEEDER_SERVERSTATUS, 0, NULL);
  4240.                 UI_BuildServerStatus(qtrue);
  4241.             }
  4242.             break;
  4243.  
  4244.         case FEEDER_PLAYER_LIST:
  4245.             uiInfo.playerIndex = index;
  4246.             break;
  4247.  
  4248.         case FEEDER_MODS:
  4249.             uiInfo.modIndex = index;
  4250.             break;
  4251.  
  4252.         case FEEDER_CINEMATICS:
  4253.             uiInfo.movieIndex = index;
  4254.             if (uiInfo.previewMovie >= 0) 
  4255.             {
  4256.                 trap_CIN_StopCinematic(uiInfo.previewMovie);
  4257.             }
  4258.             uiInfo.previewMovie = -1;
  4259.             break;
  4260.  
  4261.         case FEEDER_DEMOS:
  4262.             uiInfo.demoIndex = index;
  4263.             break;
  4264.     }
  4265. }
  4266.  
  4267. static qboolean Alias_Parse(const char **p) {
  4268.   char *token;
  4269.  
  4270.   token = COM_ParseExt(p, qtrue);
  4271.  
  4272.   if (token[0] != '{') {
  4273.     return qfalse;
  4274.   }
  4275.  
  4276.   while ( 1 ) {
  4277.     token = COM_ParseExt(p, qtrue);
  4278.  
  4279.     if (Q_stricmp(token, "}") == 0) {
  4280.       return qtrue;
  4281.     }
  4282.  
  4283.     if ( !token || token[0] == 0 ) {
  4284.       return qfalse;
  4285.     }
  4286.  
  4287.     if (token[0] == '{') {
  4288.       // three tokens per line, character name, bot alias, and preferred action a - all purpose, d - defense, o - offense
  4289.       if (!String_Parse(p, &uiInfo.aliasList[uiInfo.aliasCount].name) || !String_Parse(p, &uiInfo.aliasList[uiInfo.aliasCount].ai) || !String_Parse(p, &uiInfo.aliasList[uiInfo.aliasCount].action)) {
  4290.         return qfalse;
  4291.       }
  4292.     
  4293.       Com_Printf("Loaded character alias %s using character ai %s.\n", uiInfo.aliasList[uiInfo.aliasCount].name, uiInfo.aliasList[uiInfo.aliasCount].ai);
  4294.       if (uiInfo.aliasCount < MAX_ALIASES) {
  4295.         uiInfo.aliasCount++;
  4296.       } else {
  4297.         Com_Printf("Too many aliases, last alias replaced!\n");
  4298.       }
  4299.      
  4300.       token = COM_ParseExt(p, qtrue);
  4301.       if (token[0] != '}') {
  4302.         return qfalse;
  4303.       }
  4304.     }
  4305.   }
  4306.  
  4307.   return qfalse;
  4308. }
  4309.  
  4310. static void UI_Pause(qboolean b) 
  4311. {
  4312.     if (b) 
  4313.     {
  4314.         // pause the game and set the ui keycatcher
  4315.         trap_Cvar_Set( "cl_paused", "1" );
  4316.         trap_Key_SetCatcher( KEYCATCH_UI );
  4317.     } 
  4318.     else 
  4319.     {
  4320.         // unpause the game and clear the ui keycatcher
  4321.         trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );
  4322.         trap_Key_ClearStates();
  4323.         trap_Cvar_Set( "cl_paused", "0" );
  4324.     }
  4325. }
  4326.  
  4327. static int UI_PlayCinematic(const char *name, float x, float y, float w, float h) 
  4328. {
  4329.     return trap_CIN_PlayCinematic(name, x, y, w, h, (CIN_loop | CIN_silent));
  4330. }
  4331.  
  4332. static void UI_StopCinematic(int handle) {
  4333.     if (handle >= 0) {
  4334.       trap_CIN_StopCinematic(handle);
  4335.     } else {
  4336.         handle = abs(handle);
  4337.         if (handle == UI_MAPCINEMATIC) {
  4338.             if (uiInfo.mapList[ui_currentMap.integer].cinematic >= 0) {
  4339.               trap_CIN_StopCinematic(uiInfo.mapList[ui_currentMap.integer].cinematic);
  4340.               uiInfo.mapList[ui_currentMap.integer].cinematic = -1;
  4341.             }
  4342.         } else if (handle == UI_NETMAPCINEMATIC) {
  4343.             if (uiInfo.serverStatus.currentServerCinematic >= 0) {
  4344.               trap_CIN_StopCinematic(uiInfo.serverStatus.currentServerCinematic);
  4345.                 uiInfo.serverStatus.currentServerCinematic = -1;
  4346.             }
  4347.         } 
  4348.     }
  4349. }
  4350.  
  4351. static void UI_DrawCinematic(int handle, float x, float y, float w, float h) {
  4352.     trap_CIN_SetExtents(handle, x, y, w, h);
  4353.   trap_CIN_DrawCinematic(handle);
  4354. }
  4355.  
  4356. static void UI_RunCinematicFrame(int handle) {
  4357.   trap_CIN_RunCinematic(handle);
  4358. }
  4359.  
  4360. /*
  4361. =================
  4362. UI_Init
  4363. =================
  4364. */
  4365. void _UI_Init( qboolean inGameLoad ) 
  4366. {
  4367.     int            start;
  4368.     int            i;
  4369.     char        identity[256];
  4370.  
  4371.     UI_RegisterCvars();
  4372.  
  4373.     // cache redundant calulations
  4374.     trap_GetGlconfig( &uiInfo.uiDC.glconfig );
  4375.  
  4376.     // for 640x480 virtualized screen
  4377.     uiInfo.uiDC.yscale = uiInfo.uiDC.glconfig.vidHeight * (1.0/480.0);
  4378.     uiInfo.uiDC.xscale = uiInfo.uiDC.glconfig.vidWidth * (1.0/640.0);
  4379.     if ( uiInfo.uiDC.glconfig.vidWidth * 480 > uiInfo.uiDC.glconfig.vidHeight * 640 ) 
  4380.     {
  4381.         // wide screen
  4382.         uiInfo.uiDC.bias = 0.5 * ( uiInfo.uiDC.glconfig.vidWidth - ( uiInfo.uiDC.glconfig.vidHeight * (640.0/480.0) ) );
  4383.     }
  4384.     else 
  4385.     {
  4386.         // no wide screen
  4387.         uiInfo.uiDC.bias = 0;
  4388.     }
  4389.  
  4390.     uiInfo.uiDC.registerShaderNoMip = &trap_R_RegisterShaderNoMip;
  4391.     uiInfo.uiDC.setColor = &UI_SetColor;
  4392.     uiInfo.uiDC.drawHandlePic = &UI_DrawHandlePic;
  4393.     uiInfo.uiDC.drawStretchPic = &trap_R_DrawStretchPic;
  4394.     uiInfo.uiDC.drawText = &UI_DrawText;
  4395.     uiInfo.uiDC.drawTextWithCursor = &UI_DrawTextWithCursor;
  4396.     uiInfo.uiDC.getTextWidth = &trap_R_GetTextWidth;
  4397.     uiInfo.uiDC.getTextHeight = &trap_R_GetTextHeight;
  4398.     uiInfo.uiDC.registerModel = &trap_R_RegisterModel;
  4399.     uiInfo.uiDC.modelBounds = &trap_R_ModelBounds;
  4400.     uiInfo.uiDC.fillRect = &UI_FillRect;
  4401.     uiInfo.uiDC.drawRect = &_UI_DrawRect;
  4402.     uiInfo.uiDC.drawSides = &_UI_DrawRectLeftRight;
  4403.     uiInfo.uiDC.drawTopBottom = &_UI_DrawRectTopBottom;
  4404.     uiInfo.uiDC.clearScene = &trap_R_ClearScene;
  4405.     uiInfo.uiDC.addRefEntityToScene = &trap_R_AddRefEntityToScene;
  4406.     uiInfo.uiDC.renderScene = &trap_R_RenderScene;
  4407.     uiInfo.uiDC.registerFont = &trap_R_RegisterFont;
  4408.     uiInfo.uiDC.ownerDrawItem = &UI_OwnerDraw;
  4409.     uiInfo.uiDC.getValue = &UI_GetValue;
  4410.     uiInfo.uiDC.ownerDrawVisible = &UI_OwnerDrawVisible;
  4411.     uiInfo.uiDC.ownerDrawDisabled = &UI_OwnerDrawDisabled;
  4412.     uiInfo.uiDC.runScript = &UI_RunMenuScript;
  4413.     uiInfo.uiDC.getTeamColor = &UI_GetTeamColor;
  4414.     uiInfo.uiDC.setCVar = trap_Cvar_Set;
  4415.     uiInfo.uiDC.getCVarString = trap_Cvar_VariableStringBuffer;
  4416.     uiInfo.uiDC.getCVarValue = trap_Cvar_VariableValue;
  4417.     uiInfo.uiDC.setOverstrikeMode = &trap_Key_SetOverstrikeMode;
  4418.     uiInfo.uiDC.getOverstrikeMode = &trap_Key_GetOverstrikeMode;
  4419.     uiInfo.uiDC.startLocalSound = &trap_S_StartLocalSound;
  4420.     uiInfo.uiDC.ownerDrawHandleKey = &UI_OwnerDrawHandleKey;
  4421.     uiInfo.uiDC.feederCount = &UI_FeederCount;
  4422.     uiInfo.uiDC.feederItemImage = &UI_FeederItemImage;
  4423.     uiInfo.uiDC.feederItemText = &UI_FeederItemText;
  4424.     uiInfo.uiDC.feederSelection = &UI_FeederSelection;
  4425.     uiInfo.uiDC.setBinding = &trap_Key_SetBinding;
  4426.     uiInfo.uiDC.getBindingBuf = &trap_Key_GetBindingBuf;
  4427.     uiInfo.uiDC.keynumToStringBuf = &trap_Key_KeynumToStringBuf;
  4428.     uiInfo.uiDC.executeText = &trap_Cmd_ExecuteText;
  4429.     uiInfo.uiDC.Error = &Com_Error; 
  4430.     uiInfo.uiDC.Print = &Com_Printf; 
  4431.     uiInfo.uiDC.Pause = &UI_Pause;
  4432.     uiInfo.uiDC.ownerDrawWidth = &UI_OwnerDrawWidth;
  4433.     uiInfo.uiDC.registerSound = &trap_S_RegisterSound;
  4434.     uiInfo.uiDC.startBackgroundTrack = &trap_S_StartBackgroundTrack;
  4435.     uiInfo.uiDC.stopBackgroundTrack = &trap_S_StopBackgroundTrack;
  4436.     uiInfo.uiDC.playCinematic = &UI_PlayCinematic;
  4437.     uiInfo.uiDC.stopCinematic = &UI_StopCinematic;
  4438.     uiInfo.uiDC.drawCinematic = &UI_DrawCinematic;
  4439.     uiInfo.uiDC.runCinematicFrame = &UI_RunCinematicFrame;
  4440.  
  4441.     Init_Display(&uiInfo.uiDC);
  4442.  
  4443.     String_Init();
  4444.   
  4445.     uiInfo.uiDC.whiteShader = trap_R_RegisterShaderNoMip( "white" );
  4446.  
  4447.     AssetCache();
  4448.  
  4449.     start = trap_Milliseconds();
  4450.  
  4451.     uiInfo.aliasCount = 0;
  4452.  
  4453.     // Read in the gametype list for the various user interface screens
  4454.     BG_BuildGametypeList ( );
  4455.     BG_ParseNPCFiles ( );
  4456.  
  4457.     // Load all the menus
  4458.     if ( inGameLoad )
  4459.     {
  4460.         uiInfo.menusFile = "ui/ingame.txt";
  4461.         uiInfo.inGameLoad = qtrue;
  4462.     }
  4463.     else
  4464.     {
  4465.         uiInfo.menusFile = "ui/menus.txt";
  4466.     }
  4467.  
  4468.     UI_LoadMenus( uiInfo.menusFile, qtrue);
  4469.     
  4470.     Menus_CloseAll();
  4471.  
  4472.     trap_LAN_LoadCachedServers();
  4473.  
  4474.     UI_LoadIdentityIcons ( );
  4475.  
  4476.     // Initialize the team cvars
  4477.     trap_Cvar_Set ( "ui_info_redteam", "" );
  4478.     trap_Cvar_Set ( "ui_info_blueteam", "" );
  4479.     trap_Cvar_Set ( "ui_info_gametype", "0" );
  4480.     trap_Cvar_Set ( "ui_info_team", "0" );
  4481.  
  4482. #ifdef _SOF2_BOTS
  4483.     UI_LoadBots();
  4484. #endif
  4485.  
  4486.     // sets defaults for ui temp cvars
  4487.     uiInfo.currentCrosshair = (int)trap_Cvar_VariableValue("cg_drawCrosshair");
  4488.     trap_Cvar_Set("ui_mousePitch", (trap_Cvar_VariableValue("m_pitch") >= 0) ? "0" : "1");
  4489.  
  4490.     uiInfo.serverStatus.currentServerCinematic = -1;
  4491.     uiInfo.previewMovie = -1;
  4492.  
  4493.     if (trap_Cvar_VariableValue("ui_sof2FirstRun") == 0) 
  4494.     {
  4495.         trap_Cvar_Set("s_volume", "0.8");
  4496.         trap_Cvar_Set("s_musicvolume", "0.5");
  4497.         trap_Cvar_Set("s_attenuate", "0.00045" );
  4498.         trap_Cvar_Set("ui_sof2FirstRun", "1");
  4499.     }
  4500.  
  4501.     trap_Cvar_Register(NULL, "debug_protocol", "", 0, 0.0, 0.0 );
  4502.  
  4503.     trap_Cvar_Set("ui_actualNetGameType", va("%d", ui_netGameType.integer));
  4504.     trap_Cvar_Set("ui_gtRespawnType", va("%d", bg_gametypeData[ui_netGameType.integer].respawnType));
  4505.     trap_Cvar_Set("ui_gtPickupsDisabled", va("%d", bg_gametypeData[ui_netGameType.integer].pickupsDisabled));
  4506.  
  4507.     trap_Cvar_VariableStringBuffer("identity", identity, sizeof(identity));
  4508.     for(i=0;i<bg_identityCount;i++)
  4509.     {
  4510.         if (Q_stricmp(bg_identities[i].mName, identity) == 0)
  4511.         {
  4512.             Menu_SetFeederSelection(NULL, FEEDER_IDENTITIES, i, "player_menu");
  4513.             break;
  4514.         }
  4515.     }
  4516. }
  4517.  
  4518. /*
  4519. =================
  4520. UI_KeyEvent
  4521. =================
  4522. */
  4523. qboolean _UI_KeyEvent( int key, qboolean down ) 
  4524. {
  4525.     menuDef_t *menu;
  4526.  
  4527.     if (Menu_Count() <= 0) 
  4528.     {
  4529.         return qfalse;
  4530.     }
  4531.  
  4532.     menu = Menu_GetFocused();
  4533.     
  4534.     if (menu) 
  4535.     {
  4536.         if (key == K_ESCAPE && down && !Menus_AnyFullScreenVisible()) 
  4537.         {
  4538.             Menus_CloseAll();
  4539.         } 
  4540.         else 
  4541.         {
  4542.             // Passthrough has no mouse input
  4543.             if ( (key < '0' || key > '9') && (trap_Key_GetCatcher ( ) & KEYCATCH_NUMBERSONLY) )
  4544.             {
  4545.                 return qfalse;
  4546.             }
  4547.  
  4548.             return Menu_HandleKey(menu, key, down );
  4549.         }
  4550.     } 
  4551.     else 
  4552.     {
  4553.         int catcher = trap_Key_GetCatcher ( );
  4554.  
  4555.         if ( catcher & KEYCATCH_NUMBERSONLY )
  4556.         {
  4557.             trap_Key_SetCatcher( trap_Key_GetCatcher() & ~(KEYCATCH_UI|KEYCATCH_NUMBERSONLY) );
  4558.         }
  4559.         else
  4560.         {
  4561.             trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );
  4562.             trap_Key_ClearStates();
  4563.             trap_Cvar_Set( "cl_paused", "0" );
  4564.         }
  4565.     }
  4566.  
  4567.     return qfalse;
  4568. }
  4569.  
  4570. /*
  4571. =================
  4572. UI_MouseEvent
  4573. =================
  4574. */
  4575. qboolean _UI_MouseEvent( int dx, int dy )
  4576. {
  4577.     // update mouse screen position
  4578.     uiInfo.uiDC.cursorx += dx;
  4579.     if (uiInfo.uiDC.cursorx < 0)
  4580.         uiInfo.uiDC.cursorx = 0;
  4581.     else if (uiInfo.uiDC.cursorx > SCREEN_WIDTH)
  4582.         uiInfo.uiDC.cursorx = SCREEN_WIDTH;
  4583.  
  4584.     uiInfo.uiDC.cursory += dy;
  4585.     if (uiInfo.uiDC.cursory < 0)
  4586.         uiInfo.uiDC.cursory = 0;
  4587.     else if (uiInfo.uiDC.cursory > SCREEN_HEIGHT)
  4588.         uiInfo.uiDC.cursory = SCREEN_HEIGHT;
  4589.  
  4590.     // If the cursor has moved then reset the tooltip location and time.
  4591.     if ( uiInfo.uiDC.tooltipx != uiInfo.uiDC.cursorx ||
  4592.          uiInfo.uiDC.tooltipy != uiInfo.uiDC.cursory    )
  4593.     {
  4594.         uiInfo.uiDC.tooltipx = uiInfo.uiDC.cursorx;
  4595.         uiInfo.uiDC.tooltipy = uiInfo.uiDC.cursory;
  4596.         uiInfo.uiDC.tooltiptime = uiInfo.uiDC.realTime;
  4597.     }
  4598.  
  4599.     if (Menu_Count() > 0) 
  4600.     {
  4601.         //menuDef_t *menu = Menu_GetFocused();
  4602.         //Menu_HandleMouseMove(menu, uiInfo.uiDC.cursorx, uiInfo.uiDC.cursory);
  4603.         Display_MouseMove(NULL, uiInfo.uiDC.cursorx, uiInfo.uiDC.cursory);
  4604.     }
  4605.  
  4606.     return qtrue;
  4607. }
  4608.  
  4609. void UI_LoadNonIngame() 
  4610. {
  4611.     UI_LoadMenus("ui/menus.txt", qtrue );
  4612.     uiInfo.inGameLoad = qfalse;
  4613. }
  4614.  
  4615. void UI_SetActiveMenu( uiMenuCommand_t menu ) 
  4616. {
  4617.     char    buf[256];
  4618.  
  4619.     // this should be the ONLY way the menu system is brought up
  4620.     // enusure minumum menu data is cached
  4621.     if (Menu_Count() <= 0) 
  4622.     {    
  4623.         return;
  4624.     }
  4625.     
  4626.     switch ( menu ) 
  4627.     {
  4628.         case UIMENU_NONE:
  4629.             trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );
  4630.             trap_Key_ClearStates();
  4631.             trap_Cvar_Set( "cl_paused", "0" );
  4632.             Menus_CloseAll();
  4633.             return;
  4634.  
  4635.         case UIMENU_MAIN:
  4636.         {
  4637.             qboolean   active = qfalse;
  4638.             menuDef_t* menudef;
  4639.             itemDef_t* item;
  4640.  
  4641.             // Make sure the player setup alwasy shows non team game models
  4642.             trap_Cvar_Set ( "ui_info_teamgame", "0" );
  4643.     
  4644.             trap_Key_SetCatcher( KEYCATCH_UI );
  4645.  
  4646.             Menus_CloseAll();
  4647.  
  4648.             if (uiInfo.inGameLoad) 
  4649.             {
  4650.                 uiInfo.inGameLoad = qfalse;
  4651.                 UI_LoadNonIngame();
  4652.             }
  4653.             
  4654.             menudef = Menus_ActivateByName("main");
  4655.  
  4656.             // the ui_joinserver cvar tells us whether or not we should jump
  4657.             // straight to the join server menu
  4658.             if ( ui_joinserver.integer )
  4659.             {
  4660.                 item = Menu_GetItemByName ( menudef, "play_button" );
  4661.             }
  4662.             else
  4663.             {
  4664.                 item = NULL;
  4665.             }
  4666.  
  4667.             trap_Cvar_Set ( "ui_joinserver", "0" );
  4668.  
  4669.             if ( item )
  4670.             {
  4671.                 Item_Action ( item );
  4672.  
  4673.                 trap_Cvar_VariableStringBuffer("com_errorMessage", buf, sizeof(buf));
  4674.                 if (strlen(buf)) 
  4675.                 {
  4676.                     Menus_ActivateByName("error_popmenu");
  4677.                     active = qtrue;
  4678.                 }
  4679.             }
  4680.             else
  4681.             {
  4682.                 trap_Cvar_VariableStringBuffer("com_errorMessage", buf, sizeof(buf));
  4683.                 if (strlen(buf)) 
  4684.                 {
  4685.                     Menus_ActivateByName("error_popmenu");
  4686.                     active = qtrue;
  4687.                 }
  4688.                 
  4689.                 if (!active && ui_invalidversion.integer) 
  4690.                 {
  4691.                     Menus_ActivateByName("patch_info");
  4692.                     active = qtrue;
  4693.                 }
  4694.                 
  4695.                 if ( !active && !ui_cdkeychecked.integer )
  4696.                 {
  4697.                     char key[20];
  4698.  
  4699.                     trap_GetCDKey( key, sizeof(key) );
  4700.                     if( !trap_VerifyCDKey( key ) ) 
  4701.                     {
  4702.                         Menus_ActivateByName("cdkey_popmenu");
  4703.                         active = qtrue;
  4704.                     }
  4705.                 }
  4706.                 
  4707.                 if ( !active && (int)trap_Cvar_VariableValue ( "com_othertasks" ) )
  4708.                 {
  4709.                     trap_Cvar_Set("com_othertasks", "0");
  4710.                     if ( !(int)trap_Cvar_VariableValue ( "com_ignoreothertasks" ) )
  4711.                     {
  4712.                         Menus_ActivateByName("backgroundtask_popmenu");
  4713.                         active = qtrue;
  4714.                     }
  4715.                 }
  4716.             }
  4717.  
  4718.             return;
  4719.         }
  4720.  
  4721.         case UIMENU_VERSION:
  4722.             trap_Key_SetCatcher( KEYCATCH_UI );
  4723.             Menus_ActivateByName("patch_info");
  4724.             return;
  4725.  
  4726.         case UIMENU_BAD_CD_KEY:
  4727.             // no cd check in TA
  4728.             //trap_Key_SetCatcher( KEYCATCH_UI );
  4729.             //Menus_ActivateByName("badcd");
  4730.             //UI_ConfirmMenu( "Bad CD Key", NULL, NeedCDKeyAction );
  4731.             return;
  4732.  
  4733.          case UIMENU_INGAME:
  4734.             trap_Cvar_Set( "cl_paused", "1" );
  4735.             trap_Key_SetCatcher( KEYCATCH_UI );
  4736.             UI_BuildPlayerList();
  4737.             Menus_CloseAll();
  4738.             Menus_ActivateByName("ingame");
  4739.             return;
  4740.  
  4741.         case UIMENU_OBJECTIVES:
  4742.             trap_Key_SetCatcher( KEYCATCH_UI );
  4743.             Menus_CloseAll();
  4744.             Menus_ActivateByName("ingame_objectives");                
  4745.             return;
  4746.  
  4747.         case UIMENU_RADIO:
  4748.             trap_Key_SetCatcher( KEYCATCH_UI|KEYCATCH_NUMBERSONLY );
  4749.             Menus_CloseAll();
  4750.             Menus_ActivateByName("ingame_radio");                
  4751.             return;
  4752.  
  4753.         case UIMENU_OUTFITTING:
  4754. //            trap_Cvar_Set( "cl_paused", "1" );
  4755.             trap_Key_SetCatcher( KEYCATCH_UI );
  4756.             Menus_CloseAll();
  4757.             Menus_ActivateByName("ingame_outfitting");
  4758.             return;
  4759.  
  4760.         case UIMENU_TEAM:
  4761. //            trap_Cvar_Set( "cl_paused", "1" );
  4762.             trap_Key_SetCatcher( KEYCATCH_UI );
  4763.             Menus_CloseAll();
  4764.             Menus_ActivateByName("ingame_team");
  4765.             return;
  4766.     }
  4767. }
  4768.  
  4769. static connstate_t    lastConnState;
  4770. static char            lastLoadingText[MAX_INFO_VALUE];
  4771.  
  4772. static void UI_ReadableSize ( char *buf, int bufsize, int value )
  4773. {
  4774.     if (value > 1024*1024*1024 ) { // gigs
  4775.         Com_sprintf( buf, bufsize, "%d", value / (1024*1024*1024) );
  4776.         Com_sprintf( buf+strlen(buf), bufsize-strlen(buf), ".%02d GB", 
  4777.             (value % (1024*1024*1024))*100 / (1024*1024*1024) );
  4778.     } else if (value > 1024*1024 ) { // megs
  4779.         Com_sprintf( buf, bufsize, "%d", value / (1024*1024) );
  4780.         Com_sprintf( buf+strlen(buf), bufsize-strlen(buf), ".%02d MB", 
  4781.             (value % (1024*1024))*100 / (1024*1024) );
  4782.     } else if (value > 1024 ) { // kilos
  4783.         Com_sprintf( buf, bufsize, "%d KB", value / 1024 );
  4784.     } else { // bytes
  4785.         Com_sprintf( buf, bufsize, "%d bytes", value );
  4786.     }
  4787. }
  4788.  
  4789. // Assumes time is in msec
  4790. static void UI_PrintTime ( char *buf, int bufsize, int time ) {
  4791.     time /= 1000;  // change to seconds
  4792.  
  4793.     if (time > 3600) { // in the hours range
  4794.         Com_sprintf( buf, bufsize, "%d hr %d min", time / 3600, (time % 3600) / 60 );
  4795.     } else if (time > 60) { // mins
  4796.         Com_sprintf( buf, bufsize, "%d min %d sec", time / 60, time % 60 );
  4797.     } else  { // secs
  4798.         Com_sprintf( buf, bufsize, "%d sec", time );
  4799.     }
  4800. }
  4801.  
  4802. void Text_PaintCenter(float x, float y, qhandle_t font, float scale, vec4_t color, const char *text, float adjust ) 
  4803. {
  4804.     int len = trap_R_GetTextWidth (text, font, scale, 0 );
  4805.     
  4806.     UI_DrawText ( x - len / 2, y, font, scale, color, text, 0, 0 );
  4807. }
  4808.  
  4809.  
  4810. static void UI_DisplayDownloadInfo( const char *downloadName, float centerPoint, float yStart, float scale ) 
  4811. {
  4812.     static char dlText[]    = "Downloading:";
  4813.     static char etaText[]    = "Estimated time left:";
  4814.     static char xferText[]    = "Transfer rate:";
  4815.  
  4816.     int downloadSize, downloadCount, downloadTime;
  4817.     char dlSizeBuf[64], totalSizeBuf[64], xferRateBuf[64], dlTimeBuf[64];
  4818.     int xferRate;
  4819.     int leftWidth;
  4820.     const char *s;
  4821.  
  4822.     downloadSize = trap_Cvar_VariableValue( "cl_downloadSize" );
  4823.     downloadCount = trap_Cvar_VariableValue( "cl_downloadCount" );
  4824.     downloadTime = trap_Cvar_VariableValue( "cl_downloadTime" );
  4825.  
  4826.     leftWidth = 320;
  4827.  
  4828.     UI_SetColor(colorWhite);
  4829.     Text_PaintCenter(centerPoint, yStart, uiInfo.uiDC.Assets.defaultFont, scale, colorWhite, dlText, 0 );
  4830.     Text_PaintCenter(centerPoint, yStart + 90, uiInfo.uiDC.Assets.defaultFont, scale, colorWhite, etaText, 0 );
  4831.     Text_PaintCenter(centerPoint, yStart + 50, uiInfo.uiDC.Assets.defaultFont, scale, colorWhite, xferText, 0 );
  4832.  
  4833.     if (downloadSize > 0) {
  4834.         s = va( "%s (%d%%)", downloadName, (int)((float)downloadCount * (100.0f / (float)downloadSize)) );
  4835.     } else {
  4836.         s = downloadName;
  4837.     }
  4838.  
  4839.     Text_PaintCenter(centerPoint, yStart+15, uiInfo.uiDC.Assets.defaultFont, scale, colorMdGrey, s, 0 );
  4840.  
  4841.     UI_ReadableSize( dlSizeBuf,        sizeof dlSizeBuf,        downloadCount );
  4842.     UI_ReadableSize( totalSizeBuf,    sizeof totalSizeBuf,    downloadSize );
  4843.  
  4844.     if (downloadCount < 4096 || !downloadTime) {
  4845.         Text_PaintCenter(leftWidth, yStart+105, uiInfo.uiDC.Assets.defaultFont, scale, colorMdGrey, "estimating", 0 );
  4846.         Text_PaintCenter(leftWidth, yStart+30, uiInfo.uiDC.Assets.defaultFont, scale, colorMdGrey, va("(%s of %s copied)", dlSizeBuf, totalSizeBuf), 0 );
  4847.     } else {
  4848.         if ((uiInfo.uiDC.realTime - downloadTime) / 1000) {
  4849.             xferRate = downloadCount / ((uiInfo.uiDC.realTime - downloadTime) / 1000);
  4850.         } else {
  4851.             xferRate = 0;
  4852.         }
  4853.         UI_ReadableSize( xferRateBuf, sizeof xferRateBuf, xferRate );
  4854.  
  4855.         // Extrapolate estimated completion time
  4856.         if (downloadSize && xferRate) {
  4857.             int n = downloadSize / xferRate; // estimated time for entire d/l in secs
  4858.  
  4859.             // We do it in K (/1024) because we'd overflow around 4MB
  4860.             UI_PrintTime ( dlTimeBuf, sizeof dlTimeBuf, 
  4861.                 (n - (((downloadCount/1024) * n) / (downloadSize/1024))) * 1000);
  4862.  
  4863.             Text_PaintCenter(leftWidth, yStart+105, uiInfo.uiDC.Assets.defaultFont, scale, colorMdGrey, dlTimeBuf, 0 );
  4864.             Text_PaintCenter(leftWidth, yStart+30, uiInfo.uiDC.Assets.defaultFont, scale, colorMdGrey, va("(%s of %s copied)", dlSizeBuf, totalSizeBuf), 0 );
  4865.         } else {
  4866.             Text_PaintCenter(leftWidth, yStart+105, uiInfo.uiDC.Assets.defaultFont, scale, colorMdGrey, "estimating", 0 );
  4867.             if (downloadSize) {
  4868.                 Text_PaintCenter(leftWidth, yStart+30, uiInfo.uiDC.Assets.defaultFont, scale, colorMdGrey, va("(%s of %s copied)", dlSizeBuf, totalSizeBuf), 0 );
  4869.             } else {
  4870.                 Text_PaintCenter(leftWidth, yStart+30, uiInfo.uiDC.Assets.defaultFont, scale, colorMdGrey, va("(%s copied)", dlSizeBuf), 0 );
  4871.             }
  4872.         }
  4873.  
  4874.         if (xferRate) {
  4875.             Text_PaintCenter(leftWidth, yStart+65, uiInfo.uiDC.Assets.defaultFont, scale, colorMdGrey, va("%s/Sec", xferRateBuf), 0 );
  4876.         }
  4877.     }
  4878. }
  4879.  
  4880. /*
  4881. ========================
  4882. UI_DrawConnectScreen
  4883.  
  4884. This will also be overlaid on the cgame info screen during loading
  4885. to prevent it from blinking away too rapidly on local or lan games.
  4886. ========================
  4887. */
  4888. void UI_DrawConnectScreen( qboolean overlay ) {
  4889.     char            *s;
  4890.     uiClientState_t    cstate;
  4891.     char            info[MAX_INFO_VALUE];
  4892.     char text[256];
  4893.     float centerPoint, yStart, scale;
  4894.     
  4895.     menuDef_t *menu = Menus_FindByName("Connect");
  4896.  
  4897.     if ( !ui_joinserver.integer )
  4898.     {
  4899.         trap_Cvar_Set ( "ui_joinserver", "1" );
  4900.     }
  4901.  
  4902.     if ( !overlay && menu ) {
  4903.         Menu_Paint(menu, qtrue);
  4904.     }
  4905.  
  4906.     if (!overlay) {
  4907.         centerPoint = 320;
  4908.         yStart = 340;
  4909.         scale = 0.53f;
  4910.     } else {
  4911.         centerPoint = 340;
  4912.         yStart = 380;
  4913.         scale = 0.53f;
  4914.         return;
  4915.     }
  4916.  
  4917.     // see what information we should display
  4918.     trap_GetClientState( &cstate );
  4919.  
  4920.     if ( cstate.connState == CA_CONNECTED )
  4921.     {
  4922.         char downloadName[MAX_INFO_VALUE];
  4923.  
  4924.         trap_Cvar_VariableStringBuffer( "cl_downloadName", downloadName, sizeof(downloadName) );
  4925.         if (*downloadName) 
  4926.         {
  4927.             if (!Q_stricmp(cstate.servername,"localhost")) 
  4928.             {
  4929.                 Text_PaintCenter(centerPoint, 50, uiInfo.uiDC.Assets.defaultFont, scale, colorWhite, va("Loading..."), 0 );
  4930.             } 
  4931.             else 
  4932.             {
  4933.                 strcpy(text, va("Connecting to %s", cstate.servername));
  4934.                 Text_PaintCenter(centerPoint, 50, uiInfo.uiDC.Assets.defaultFont, scale, colorWhite,text , 0 );
  4935.             }
  4936.  
  4937.             UI_DisplayDownloadInfo( downloadName, centerPoint, yStart, 0.43f );
  4938.             return;
  4939.         }
  4940.     }
  4941.                     
  4942.     info[0] = '\0';
  4943.     if( trap_GetConfigString( CS_SERVERINFO, info, sizeof(info) ) ) 
  4944.     {
  4945.         Text_PaintCenter(centerPoint, yStart, uiInfo.uiDC.Assets.defaultFont, scale, colorWhite, va( "Loading %s", Info_ValueForKey( info, "mapname" )), 0 );
  4946.     }
  4947.  
  4948.     if (!Q_stricmp(cstate.servername,"localhost")) 
  4949.     {
  4950.         Text_PaintCenter(centerPoint, yStart + 48, uiInfo.uiDC.Assets.defaultFont, scale, colorWhite, va("Loading..."), 0 );
  4951.     } 
  4952.     else 
  4953.     {
  4954.         strcpy(text, va("Connecting to %s", cstate.servername));
  4955.         Text_PaintCenter(centerPoint, yStart + 48, uiInfo.uiDC.Assets.defaultFont, scale, colorWhite,text , 0 );
  4956.     }
  4957.  
  4958.     // display global MOTD at bottom
  4959.     Text_PaintCenter(centerPoint, 600, uiInfo.uiDC.Assets.defaultFont, scale, colorWhite, Info_ValueForKey( cstate.updateInfoString, "motd" ), 0 );
  4960.     
  4961.     // print any server info (server full, bad version, etc)
  4962.     if ( cstate.connState < CA_CONNECTED ) 
  4963.     {
  4964.         // Display the password dialog
  4965.         if ( strstr ( cstate.messageString, "password" ) )
  4966.         {
  4967.             if ( !uiInfo.connectPasswordRequest )
  4968.             {
  4969.                 char password[MAX_QPATH];
  4970.                 trap_Cvar_VariableStringBuffer ( "password", password, MAX_QPATH );
  4971.  
  4972.                 // Dont bring it up again until the server says that password was bad too
  4973.                 if ( strstr ( cstate.messageString, password ) )
  4974.                 {
  4975.                     trap_Key_SetCatcher( KEYCATCH_UI );
  4976.                     Menus_CloseAll ( );
  4977.                     Menus_ActivateByName("password_popmenu");
  4978.                     uiInfo.connectPasswordRequest = qtrue;
  4979.                 }
  4980.             }
  4981.         }
  4982.         
  4983.         Text_PaintCenter(centerPoint, yStart + 112, uiInfo.uiDC.Assets.defaultFont, scale, colorRed, cstate.messageString, 0 );
  4984.     }
  4985.  
  4986.     if ( lastConnState > cstate.connState ) {
  4987.         lastLoadingText[0] = '\0';
  4988.     }
  4989.     lastConnState = cstate.connState;
  4990.  
  4991.     switch ( cstate.connState ) {
  4992.     case CA_CONNECTING:
  4993.         s = va("Awaiting connection...%i", cstate.connectPacketCount);
  4994.         break;
  4995.     case CA_CHALLENGING:
  4996.         s = va("Awaiting challenge...%i", cstate.connectPacketCount);
  4997.         break;
  4998.     case CA_CONNECTED:
  4999.         s = "Awaiting gamestate";
  5000.         break;
  5001.     case CA_LOADING:
  5002.         return;
  5003.     case CA_PRIMED:
  5004.         return;
  5005.     default:
  5006.         return;
  5007.     }
  5008.  
  5009.  
  5010.     if (Q_stricmp(cstate.servername,"localhost")) {
  5011.         Text_PaintCenter(centerPoint, yStart + 80, uiInfo.uiDC.Assets.defaultFont, scale, colorWhite, s, 0 );
  5012.     }
  5013.  
  5014.     // password required / connection rejected information goes here
  5015. }
  5016.  
  5017.  
  5018.  
  5019. /*
  5020. ========================
  5021. UI_DrawConnectScreen
  5022.  
  5023. This will also be overlaid on the cgame info screen during loading
  5024. to prevent it from blinking away too rapidly on local or lan games.
  5025. ========================
  5026. */
  5027. void UI_DrawLoadingScreen( void ) 
  5028. {
  5029.     float centerPoint, yStart, scale;
  5030.     
  5031.     menuDef_t *menu = Menus_FindByName("Loading");
  5032.  
  5033.     if ( menu ) 
  5034.     {
  5035.         Menu_Paint(menu, qtrue);
  5036.     }
  5037.  
  5038.     centerPoint = 320;
  5039.     yStart = 388;
  5040.     scale = 0.53f;
  5041.  
  5042.     Text_PaintCenter(centerPoint, yStart, uiInfo.uiDC.Assets.defaultFont, scale, colorWhite, "Loading...", 0 );
  5043. }
  5044.  
  5045.  
  5046. /*
  5047. ================
  5048. cvars
  5049. ================
  5050. */
  5051.  
  5052. typedef struct 
  5053. {
  5054.     vmCvar_t    *vmCvar;
  5055.     char        *cvarName;
  5056.     char        *defaultString;
  5057.     int            cvarFlags;
  5058.     float        mMinValue, mMaxValue;
  5059. } cvarTable_t;
  5060.  
  5061. vmCvar_t    ui_arenasFile;
  5062. vmCvar_t    ui_botsFile;
  5063. vmCvar_t    ui_botSkill;
  5064.  
  5065. vmCvar_t    ui_browserMaster;
  5066. vmCvar_t    ui_browserGameType;
  5067. vmCvar_t    ui_browserSortKey;
  5068. vmCvar_t    ui_browserShowFull;
  5069. vmCvar_t    ui_browserShowEmpty;
  5070.  
  5071. vmCvar_t    ui_drawCrosshair;
  5072. vmCvar_t    ui_drawCrosshairNames;
  5073.  
  5074. vmCvar_t    ui_server1;
  5075. vmCvar_t    ui_server2;
  5076. vmCvar_t    ui_server3;
  5077. vmCvar_t    ui_server4;
  5078. vmCvar_t    ui_server5;
  5079. vmCvar_t    ui_server6;
  5080. vmCvar_t    ui_server7;
  5081. vmCvar_t    ui_server8;
  5082. vmCvar_t    ui_server9;
  5083. vmCvar_t    ui_server10;
  5084. vmCvar_t    ui_server11;
  5085. vmCvar_t    ui_server12;
  5086. vmCvar_t    ui_server13;
  5087. vmCvar_t    ui_server14;
  5088. vmCvar_t    ui_server15;
  5089. vmCvar_t    ui_server16;
  5090.  
  5091. vmCvar_t    ui_cdkeychecked;
  5092. vmCvar_t    ui_invalidversion;
  5093. vmCvar_t    ui_downloadsize;
  5094. vmCvar_t    ui_downloadsite;
  5095. vmCvar_t    ui_downloadstatus;
  5096.  
  5097. vmCvar_t    ui_dedicated;
  5098. vmCvar_t    ui_gameType;
  5099. vmCvar_t    ui_netGameType;
  5100. vmCvar_t    ui_actualNetGameType;
  5101. vmCvar_t    ui_gtRespawnType;
  5102. vmCvar_t    ui_gtPickupsDisabled;
  5103. vmCvar_t    ui_joinGameType;
  5104. vmCvar_t    ui_netSource;
  5105. vmCvar_t    ui_serverFilterType;
  5106. vmCvar_t    ui_currentMap;
  5107. vmCvar_t    ui_currentNetMap;
  5108. vmCvar_t    ui_mapIndex;
  5109. vmCvar_t    ui_selectedPlayer;
  5110. vmCvar_t    ui_selectedPlayerName;
  5111. vmCvar_t    ui_lastServerRefresh_0;
  5112. vmCvar_t    ui_lastServerRefresh_1;
  5113. vmCvar_t    ui_lastServerRefresh_2;
  5114. vmCvar_t    ui_lastServerRefresh_3;
  5115. vmCvar_t    ui_scoreLimit;
  5116. vmCvar_t    ui_findPlayer;
  5117. vmCvar_t    ui_hudFiles;
  5118. vmCvar_t    ui_realWarmUp;
  5119. vmCvar_t    ui_serverStatusTimeOut;
  5120. vmCvar_t    ui_glCustom;
  5121. vmCvar_t    ui_botteam;
  5122.  
  5123. vmCvar_t    ui_rmg_config;
  5124. vmCvar_t    ui_rmg_size;
  5125. vmCvar_t    ui_rmg_time;
  5126. vmCvar_t    ui_rmg_seed;
  5127.  
  5128. // Readonly cvars used to transfer information from cgame to ui
  5129. vmCvar_t    ui_info_redteam;
  5130. vmCvar_t    ui_info_blueteam;
  5131. vmCvar_t    ui_info_redcount;
  5132. vmCvar_t    ui_info_bluecount;
  5133. vmCvar_t    ui_info_objectives;
  5134. vmCvar_t    ui_info_gametype;
  5135. vmCvar_t    ui_info_team;
  5136. vmCvar_t    ui_info_teamgame;
  5137. vmCvar_t    ui_info_redscore;
  5138. vmCvar_t    ui_info_bluescore;
  5139. vmCvar_t    ui_joinserver;
  5140.  
  5141. vmCvar_t    ui_allowparental;
  5142.  
  5143. vmCvar_t    ui_noNetCheck;
  5144.  
  5145. static cvarTable_t cvarTable[] = 
  5146. {
  5147.     { &ui_botteam, "ui_botteam", "auto", 0 },
  5148.     { &ui_glCustom, "ui_glCustom", "0", CVAR_ARCHIVE },
  5149.  
  5150.     { &ui_botsFile, "g_botsFile", "", CVAR_INIT|CVAR_ROM },
  5151.     { &ui_botSkill, "g_botSkill", "2", CVAR_ARCHIVE },
  5152.  
  5153.     { &ui_browserMaster, "ui_browserMaster", "0", CVAR_ARCHIVE },
  5154.     { &ui_browserGameType, "ui_browserGameType", "0", CVAR_ARCHIVE },
  5155.     { &ui_browserSortKey, "ui_browserSortKey", "4", CVAR_ARCHIVE },
  5156.     { &ui_browserShowFull, "ui_browserShowFull", "1", CVAR_ARCHIVE },
  5157.     { &ui_browserShowEmpty, "ui_browserShowEmpty", "1", CVAR_ARCHIVE },
  5158.  
  5159.     { &ui_drawCrosshair, "cg_drawCrosshair", "4", CVAR_ARCHIVE },
  5160.     { &ui_drawCrosshairNames, "cg_drawCrosshairNames", "1", CVAR_ARCHIVE },
  5161.  
  5162.     { &ui_server1, "server1", "", CVAR_ARCHIVE },
  5163.     { &ui_server2, "server2", "", CVAR_ARCHIVE },
  5164.     { &ui_server3, "server3", "", CVAR_ARCHIVE },
  5165.     { &ui_server4, "server4", "", CVAR_ARCHIVE },
  5166.     { &ui_server5, "server5", "", CVAR_ARCHIVE },
  5167.     { &ui_server6, "server6", "", CVAR_ARCHIVE },
  5168.     { &ui_server7, "server7", "", CVAR_ARCHIVE },
  5169.     { &ui_server8, "server8", "", CVAR_ARCHIVE },
  5170.     { &ui_server9, "server9", "", CVAR_ARCHIVE },
  5171.     { &ui_server10, "server10", "", CVAR_ARCHIVE },
  5172.     { &ui_server11, "server11", "", CVAR_ARCHIVE },
  5173.     { &ui_server12, "server12", "", CVAR_ARCHIVE },
  5174.     { &ui_server13, "server13", "", CVAR_ARCHIVE },
  5175.     { &ui_server14, "server14", "", CVAR_ARCHIVE },
  5176.     { &ui_server15, "server15", "", CVAR_ARCHIVE },
  5177.     { &ui_server16, "server16", "", CVAR_ARCHIVE },
  5178.     { &ui_cdkeychecked, "ui_cdkeychecked", "0", CVAR_ROM },
  5179.     { &ui_invalidversion, "ui_invalidversion", "0", CVAR_TEMP },
  5180.     { &ui_downloadsize, "ui_downloadsize", "0", CVAR_TEMP },
  5181.     { &ui_downloadsite, "ui_downloadsite", "0", CVAR_TEMP },
  5182.     { &ui_downloadstatus, "ui_downloadstatus", "0", CVAR_TEMP },
  5183.     { &ui_new, "ui_new", "0", CVAR_TEMP },
  5184.     { &ui_debug, "ui_debug", "0", CVAR_TEMP },
  5185.     { &ui_initialized, "ui_initialized", "0", CVAR_TEMP },
  5186.     { &ui_dedicated, "ui_dedicated", "0", CVAR_ARCHIVE },
  5187.     { &ui_gameType, "ui_gametype", "3", CVAR_ARCHIVE },
  5188.     { &ui_joinGameType, "ui_joinGametype", "0", CVAR_ARCHIVE },
  5189.     { &ui_netGameType, "ui_netGametype", "3", CVAR_ARCHIVE | CVAR_INTERNAL | CVAR_ROM },
  5190.     { &ui_actualNetGameType, "ui_actualNetGametype", "3", CVAR_ARCHIVE | CVAR_INTERNAL | CVAR_ROM },
  5191.     { &ui_gtRespawnType, "ui_gtRespawnType", "0", CVAR_ARCHIVE | CVAR_INTERNAL | CVAR_ROM },
  5192.     { &ui_gtPickupsDisabled, "ui_gtPickupsDisabled", "0", CVAR_ARCHIVE | CVAR_INTERNAL | CVAR_ROM }, 
  5193.     { &ui_netSource, "ui_netSource", "0", CVAR_ARCHIVE },
  5194.     { &ui_currentMap, "ui_currentMap", "0", CVAR_ARCHIVE },
  5195.     { &ui_currentNetMap, "ui_currentNetMap", "0", CVAR_ARCHIVE },
  5196.     { &ui_mapIndex, "ui_mapIndex", "0", CVAR_ARCHIVE },
  5197.     { &ui_selectedPlayer, "cg_selectedPlayer", "0", CVAR_ARCHIVE},
  5198.     { &ui_selectedPlayerName, "cg_selectedPlayerName", "", CVAR_ARCHIVE},
  5199.     { &ui_lastServerRefresh_0, "ui_lastServerRefresh_0", "", CVAR_ARCHIVE},
  5200.     { &ui_lastServerRefresh_1, "ui_lastServerRefresh_1", "", CVAR_ARCHIVE},
  5201.     { &ui_lastServerRefresh_2, "ui_lastServerRefresh_2", "", CVAR_ARCHIVE},
  5202.     { &ui_lastServerRefresh_3, "ui_lastServerRefresh_3", "", CVAR_ARCHIVE},
  5203.     { &ui_scoreLimit, "ui_scoreLimit", "10", 0},
  5204.     { &ui_findPlayer, "ui_findPlayer", "unknown", CVAR_ARCHIVE},
  5205.     { &ui_hudFiles, "cg_hudFiles", "ui/hud.txt", CVAR_ARCHIVE},
  5206.     { &ui_sof2FirstRun, "ui_sof2FirstRun", "0", CVAR_ARCHIVE},
  5207.     { &ui_realWarmUp, "g_warmup", "20", CVAR_ARCHIVE},
  5208.     { &ui_serverStatusTimeOut, "ui_serverStatusTimeOut", "7000", CVAR_ARCHIVE},
  5209.  
  5210.     { &ui_rmg_config,        "ui_rmg_config",        "desert",                        CVAR_ARCHIVE },
  5211.     { &ui_rmg_size,            "ui_rmg_size",            "small",                        CVAR_ARCHIVE },
  5212.     { &ui_rmg_time,            "ui_rmg_time",            "day",                            CVAR_ARCHIVE },
  5213.     { &ui_rmg_seed,            "ui_rmg_seed",            "0",                            CVAR_ARCHIVE },
  5214.  
  5215.     // Readonly cvars used to transfer information from cgame to ui
  5216.     { &ui_info_redteam,        "ui_info_redteam",        "0", CVAR_ROM|CVAR_INTERNAL },
  5217.     { &ui_info_blueteam,    "ui_info_blueteam",        "0", CVAR_ROM|CVAR_INTERNAL },
  5218.     { &ui_info_redcount,    "ui_info_redcount",        "0", CVAR_ROM|CVAR_INTERNAL },
  5219.     { &ui_info_bluecount,    "ui_info_bluecount",    "0", CVAR_ROM|CVAR_INTERNAL },
  5220.     { &ui_info_redscore,    "ui_info_redscore",        "0", CVAR_ROM|CVAR_INTERNAL },
  5221.     { &ui_info_bluescore,    "ui_info_bluescore",    "0", CVAR_ROM|CVAR_INTERNAL },
  5222.     { &ui_info_objectives,    "ui_info_objectives",    "0", CVAR_ROM|CVAR_INTERNAL },
  5223.     { &ui_info_gametype,    "ui_info_gametype",        "0", CVAR_ROM|CVAR_INTERNAL },
  5224.     { &ui_info_team,        "ui_info_team",            "0", CVAR_ROM|CVAR_INTERNAL },
  5225.     { &ui_info_teamgame,    "ui_info_teamgame",        "0", CVAR_ROM|CVAR_INTERNAL },
  5226.  
  5227.     { &ui_joinserver,        "ui_joinserver",        "0", CVAR_ROM|CVAR_INTERNAL },
  5228.  
  5229.     { &ui_allowparental,    "ui_allowparental",        "1", CVAR_ROM | CVAR_INTERNAL | CVAR_PARENTAL },
  5230.  
  5231.     { &ui_noNetCheck,        "ui_noNetCheck",        "0", CVAR_ARCHIVE },
  5232. };
  5233.  
  5234. static int    cvarTableSize = sizeof(cvarTable) / sizeof(cvarTable[0]);
  5235.  
  5236. /*
  5237. =================
  5238. UI_RegisterCvars
  5239. =================
  5240. */
  5241. void UI_RegisterCvars( void ) 
  5242. {
  5243.     int            i;
  5244.     cvarTable_t    *cv;
  5245.  
  5246.     for ( i = 0, cv = cvarTable ; i < cvarTableSize ; i++, cv++ ) 
  5247.     {
  5248.         trap_Cvar_Register( cv->vmCvar, cv->cvarName, cv->defaultString, cv->cvarFlags, cv->mMinValue, cv->mMaxValue );
  5249.     }
  5250.  
  5251.     trap_Cvar_Register(NULL, "lock_password",    "", CVAR_INTERNAL, 0.0, 0.0 );
  5252.     trap_Cvar_Register(NULL, "lock_blood",        "0", CVAR_INTERNAL, 0.0, 0.0 );
  5253.     trap_Cvar_Register(NULL, "lock_deaths",        "0", CVAR_INTERNAL, 0.0, 0.0 );
  5254.     trap_Cvar_Register(NULL, "lock_sever",        "0", CVAR_INTERNAL, 0.0, 0.0 );
  5255. }
  5256.  
  5257. /*
  5258. =================
  5259. UI_UpdateCvars
  5260. =================
  5261. */
  5262. void UI_UpdateCvars( void ) 
  5263. {
  5264.     int            i;
  5265.     cvarTable_t    *cv;
  5266.  
  5267.     for ( i = 0, cv = cvarTable ; i < cvarTableSize ; i++, cv++ ) 
  5268.     {
  5269.         int modificationCount = cv->vmCvar->modificationCount;
  5270.  
  5271.         trap_Cvar_Update( cv->vmCvar );
  5272.  
  5273.         if ( cv->vmCvar->modificationCount != modificationCount )
  5274.         {
  5275.             if ( Q_stricmp ( cv->cvarName, "ui_info_redteam" ) == 0 )
  5276.             {
  5277.                 int     count;
  5278.                 int     i;
  5279.  
  5280.                 memset ( &uiInfo.identityTeams[TEAM_RED], 0, sizeof(TIdentity*) * MAX_TEAMIDENTITIES );
  5281.  
  5282.                 if ( cv->vmCvar->string[0] )
  5283.                 {
  5284.                     for ( i = 0, count = 0; i < bg_identityCount && count < MAX_TEAMIDENTITIES; i ++ )
  5285.                     {
  5286.                         if ( Q_stricmp ( bg_identities[i].mTeam, cv->vmCvar->string ) == 0 )
  5287.                         {
  5288.                             uiInfo.identityTeams[TEAM_RED][count++] = &bg_identities[i];
  5289.                         }
  5290.                     }
  5291.                 }
  5292.             }
  5293.             else if ( Q_stricmp ( cv->cvarName, "ui_info_blueteam" ) == 0 )
  5294.             {
  5295.                 int     count;
  5296.                 int     i;
  5297.  
  5298.                 memset ( &uiInfo.identityTeams[TEAM_BLUE], 0, sizeof(TIdentity*) * MAX_TEAMIDENTITIES );
  5299.  
  5300.                 if ( cv->vmCvar->string[0] )
  5301.                 {
  5302.                     for ( i = 0, count = 0; i < bg_identityCount && count < MAX_TEAMIDENTITIES; i ++ )
  5303.                     {
  5304.                         if ( Q_stricmp ( bg_identities[i].mTeam, cv->vmCvar->string ) == 0 )
  5305.                         {
  5306.                             uiInfo.identityTeams[TEAM_BLUE][count++] = &bg_identities[i];
  5307.                         }
  5308.                     }
  5309.                 }
  5310.             }
  5311.         }
  5312.     }
  5313. }
  5314.  
  5315.  
  5316. /*
  5317. =================
  5318. ArenaServers_StopRefresh
  5319. =================
  5320. */
  5321. static void UI_StopServerRefresh( void )
  5322. {
  5323.     int count;
  5324.  
  5325.     if (!uiInfo.serverStatus.refreshActive) {
  5326.         // not currently refreshing
  5327.         return;
  5328.     }
  5329.     uiInfo.serverStatus.refreshActive = qfalse;
  5330.     Com_Printf("%d servers listed in browser with %d players.\n",
  5331.                     uiInfo.serverStatus.numDisplayServers,
  5332.                     uiInfo.serverStatus.numPlayersOnServers);
  5333.     count = trap_LAN_GetServerCount(ui_netSource.integer);
  5334.     if (count - uiInfo.serverStatus.numDisplayServers > 0) {
  5335.         Com_Printf("%d servers not listed due to packet loss or pings higher than %d\n",
  5336.                         count - uiInfo.serverStatus.numDisplayServers,
  5337.                         (int) trap_Cvar_VariableValue("cl_maxPing"));
  5338.     }
  5339.  
  5340. }
  5341.  
  5342. /*
  5343. =================
  5344. ArenaServers_MaxPing
  5345. =================
  5346. */
  5347. #ifndef MISSIONPACK // bk001206
  5348. static int ArenaServers_MaxPing( void ) {
  5349.     int        maxPing;
  5350.  
  5351.     maxPing = (int)trap_Cvar_VariableValue( "cl_maxPing" );
  5352.     if( maxPing < 100 ) {
  5353.         maxPing = 100;
  5354.     }
  5355.     return maxPing;
  5356. }
  5357. #endif
  5358.  
  5359. /*
  5360. =================
  5361. UI_DoServerRefresh
  5362. =================
  5363. */
  5364. static void UI_DoServerRefresh( void )
  5365. {
  5366.     qboolean wait = qfalse;
  5367.  
  5368.     if (!uiInfo.serverStatus.refreshActive) {
  5369.         return;
  5370.     }
  5371.     if (ui_netSource.integer != AS_FAVORITES) {
  5372.         if (ui_netSource.integer == AS_LOCAL) {
  5373.             if (!trap_LAN_GetServerCount(ui_netSource.integer)) {
  5374.                 wait = qtrue;
  5375.             }
  5376.         } else {
  5377.             if (trap_LAN_GetServerCount(ui_netSource.integer) < 0) {
  5378.                 wait = qtrue;
  5379.             }
  5380.         }
  5381.     }
  5382.  
  5383.     if (uiInfo.uiDC.realTime < uiInfo.serverStatus.refreshtime) {
  5384.         if (wait) {
  5385.             return;
  5386.         }
  5387.     }
  5388.  
  5389.     // if still trying to retrieve pings
  5390.     if (trap_LAN_UpdateVisiblePings(ui_netSource.integer)) {
  5391.         uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime + 1000;
  5392.     } else if (!wait) {
  5393.         // get the last servers in the list
  5394.         UI_BuildServerDisplayList(2);
  5395.         // stop the refresh
  5396.         UI_StopServerRefresh();
  5397.     }
  5398.     //
  5399.     UI_BuildServerDisplayList(qfalse);
  5400. }
  5401.  
  5402. /*
  5403. =================
  5404. UI_StartServerRefresh
  5405. =================
  5406. */
  5407. static void UI_StartServerRefresh ( qboolean full )
  5408. {
  5409.     char*    ptr;
  5410.     qtime_t q;
  5411.  
  5412.     trap_RealTime(&q);
  5413.      trap_Cvar_Set( va("ui_lastServerRefresh_%i", ui_netSource.integer), va("%s-%i, %i at %i:%i", MonthAbbrev[q.tm_mon],q.tm_mday, 1900+q.tm_year,q.tm_hour,q.tm_min));
  5414.  
  5415.     if (!full) 
  5416.     {
  5417.         UI_UpdatePendingPings();
  5418.         return;
  5419.     }
  5420.  
  5421.     uiInfo.serverStatus.refreshActive = qtrue;
  5422.     uiInfo.serverStatus.nextDisplayRefresh = uiInfo.uiDC.realTime + 1000;
  5423.  
  5424.     // clear number of displayed servers
  5425.     uiInfo.serverStatus.numDisplayServers = 0;
  5426.     uiInfo.serverStatus.numPlayersOnServers = 0;
  5427.  
  5428.     // mark all servers as visible so we store ping updates for them
  5429.     trap_LAN_MarkServerVisible(ui_netSource.integer, -1, qtrue);
  5430.     
  5431.     // reset all the pings
  5432.     trap_LAN_ResetPings(ui_netSource.integer);
  5433.  
  5434.     if( ui_netSource.integer == AS_LOCAL ) 
  5435.     {
  5436.         trap_Cmd_ExecuteText( EXEC_NOW, "localservers\n" );
  5437.         uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime + 1000;
  5438.         return;
  5439.     }
  5440.  
  5441.     uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime + 5000;
  5442.     if( ui_netSource.integer == AS_GLOBAL  ) 
  5443.     {
  5444.         ptr = UI_Cvar_VariableString("debug_protocol");
  5445.         if (strlen(ptr)) 
  5446.         {
  5447.             trap_Cmd_ExecuteText( EXEC_NOW, va( "globalservers 0 %s\n", ptr));
  5448.         }
  5449.         else 
  5450.         {
  5451.             trap_Cmd_ExecuteText( EXEC_NOW, va( "globalservers 0 %d\n", (int)trap_Cvar_VariableValue( "protocol" ) ) );
  5452.         }
  5453.     }
  5454. }
  5455.  
  5456.